Array covariance is the principle that if an implicit or explicit reference conversion exits from type A to B, then the
same conversion exists from the array type A[] to B[].
While this array conversion can be useful in readonly situations to pass instances of A[] where B[] is expected, it must
be used with care, since assigning an instance of B into an array of A will cause an ArrayTypeMismatchException
to be thrown at runtime.
Noncompliant code example
abstract class Fruit { }
class Apple : Fruit { }
class Orange : Fruit { }
class Program
{
  static void Main(string[] args)
  {
    Fruit[] fruits = new Apple[1]; // Noncompliant - array covariance is used
    FillWithOranges(fruits);
  }
  // Just looking at the code doesn't reveal anything suspicious
  static void FillWithOranges(Fruit[] fruits)
  {
    for (int i = 0; i < fruits.Length; i++)
    {
      fruits[i] = new Orange(); // Will throw an ArrayTypeMismatchException
    }
  }
}
Compliant solution
abstract class Fruit { }
class Apple : Fruit { }
class Orange : Fruit { }
class Program
{
  static void Main(string[] args)
  {
    Orange[] fruits = new Orange[1]; // Compliant
    FillWithOranges(fruits);
  }
  static void FillWithOranges(Orange[] fruits)
  {
    for (int i = 0; i < fruits.Length; i++)
    {
      fruits[i] = new Orange();
    }
  }
}