== Why is this an issue?

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

[source,csharp]
----
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

[source,csharp]
----
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();
    }
  }
}
----


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Refactor the code to not rely on potentially unsafe array conversions.


'''
== Comments And Links
(visible only on this page)

=== relates to: S3062

=== on 11 May 2015, 14:33:24 Dinesh Bolkensteyn wrote:
I don't get this explanation - I think we need a real example where something fails

=== on 12 May 2015, 13:09:33 Ann Campbell wrote:
how 'bout now [~dinesh.bolkensteyn]?

=== on 12 May 2015, 16:20:25 Dinesh Bolkensteyn wrote:
Note that we probably also want an issue here:


----
FillWithOranges(new Apple[1]); // Noncompliant
void FillWithOranges(Fruit[] fruits) { fruits[0] = new Orange(); }
----

and that, in an ideal world, we would actually be able to flag the ``++FillWithOranges++`` method which should be refactored to take ``++Orange[]++`` as argument


I'm thinking that we can change this rule to something like: Don't assign into arrays of A when there exists subtypes of A.


So, on the trivial example:

----
object[] a = new string[42]; // This is actually OK - as long as we only plan to read from "a" then nothing bad will happen
a[0] = 42; // Noncompliant - here the rule determines that "a" is an array of "object", for which it is able to find many derived types ({{string}}, {{Int32}}, etc.)
----

WDYT [~ann.campbell.2]?

=== on 14 May 2015, 12:51:42 Ann Campbell wrote:
thanks [~dinesh.bolkensteyn]

=== on 15 Jun 2015, 12:48:51 Tamas Vajk wrote:
\[~ann.campbell.2] this rule is missing the severity and scale mappings

=== on 15 Jun 2015, 13:13:21 Tamas Vajk wrote:
\[~ann.campbell.2] can you create a separate rule, which is an actual bug detection rule based on this one?


This rule says that we should report on ``++Fruit[] fruits = new Apple[1];++``, however, that's perfectly fine, that line won't throw an exception. The problem comes when we try to put a non-``++Apple++`` derived fruit in the array. So we should mark this line: ``++fruits[i] = new Orange();++`` that there is a potential bug here. 


However, currently we have no way of finding these real bugs. So that's why I would create a separate rule.

=== on 15 Jun 2015, 14:24:22 Ann Campbell wrote:
\[~tamas.vajk] SQALE was already there. I've added severity

=== on 15 Jun 2015, 14:47:57 Tamas Vajk wrote:
\[~ann.campbell.2] True, and it should be disabled by default, if I'm right?

=== on 16 Jun 2015, 11:31:44 Ann Campbell wrote:
Correct [~tamas.vajk]

endif::env-github,rspecator-view[]
