Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Resharper say, "Co-variant array conversion from string[] to object[] can cause run-time exception on write operation" with this code? [duplicate]

This code:

comboBoxMonth.Items.AddRange(UsageRptConstsAndUtils.months.ToArray());  public static List<String> months = new List<String> {     "Jan",     "Feb",     "Mar",     "Apr",     "May",     "Jun",     "Jul",     "Aug",     "Sep",     "Oct",     "Nov",     "Dec" }; 

Turns R# curmudgeon-like with the complaint, "Co-variant array conversion from string[] to object[] can cause run-time exception on write operation".

Actually, this code works perfectly - the combo box is populated with the month values; what is Resharper on about, and what can I do to assuage its doubts?

If it's simply that the generic list may contain bad data, I won't worry about it - and if there ever were a problem, it would be easy enough to track down the problem.

like image 534
B. Clay Shannon-B. Crow Raven Avatar asked Nov 05 '15 22:11

B. Clay Shannon-B. Crow Raven


2 Answers

The method comboBoxMonth.Items.AddRange expects an object[] parameter. months.ToArray() is string[]. A cast from string[] to object[] is valid, but if the method tries to modify elements of the array, you will get run-time errors. In this case it doesn't, so you can ignore the warning.

If it annoys you, you can use ToArray<object>()

comboBoxMonth.Items.AddRange(UsageRptConstsAndUtils.months.ToArray<object>()); 

It will return object[] and no cast will be needed.

like image 75
Jakub Lortz Avatar answered Sep 17 '22 11:09

Jakub Lortz


An example to demonstrate the problem:

void Main() {     Animal[] animals = new Girafee[2];     animals[0] = new Zebra(); }  public class Animal { } public class Girafee : Animal { } public class Zebra : Animal { } 

This will throw a ArrayTypeMismatchException at run-time.

R# is basically hinting you of a possible problem of the fact that you're assigning a string[] to an object[], which is completely allowed by the compiler, but may lead to a run-time exception if an object, which shares the same base class, is assigned to the array of which already points to a different type (as in my example, we actually point to a girafee array). Array co-variance is broken in the meaning that it doesn't supply you with the compile-time safety you get with generics.

Eric Lippert talks about this in Covariance and Contravariance in C#, Part Two: Array Covariance:

Unfortunately, this particular kind of covariance is broken. It was added to the CLR because Java requires it and the CLR designers wanted to be able to support Java-like languages. We then up and added it to C# because it was in the CLR. This decision was quite controversial at the time and I am not very happy about it, but there’s nothing we can do about it now.

Why is this broken? Because it should always be legal to put a Turtle into an array of Animals. With array covariance in the language and runtime you cannot guarantee that an array of Animals can accept a Turtle because the backing store might actually be an array of Giraffes.

like image 22
Yuval Itzchakov Avatar answered Sep 21 '22 11:09

Yuval Itzchakov