为什么Resharper说,“从字符串[]到对象[]的共变量数组转换会导致写入操作的运行时异常”使用此代码?

时间:2015-11-05 22:01:20

标签: c# resharper string-conversion covariant covariant-return-types

此代码:

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"
};

与投诉一样转变R#curmudgeon,“从字符串[]到对象[]的共变量数组转换可能导致写入操作的运行时异常”。

实际上,此代码完美无缺 - 组合框中填充了月份值;什么是Resharper,我该怎么做才能缓解它的疑虑?

如果只是通用列表可能包含错误数据,我不会担心 - 如果遇到问题,那么追踪问题就很容易了。

2 个答案:

答案 0 :(得分:30)

方法comboBoxMonth.Items.AddRange需要object[]参数。 months.ToArray()string[]。从string[]object[]的强制转换有效,但如果该方法尝试修改数组的元素,则会出现运行时错误。在这种情况下它没有,所以你可以忽略警告。

如果它让您烦恼,可以使用ToArray<object>()

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

它将返回object[],不需要演员。

答案 1 :(得分:15)

证明问题的一个例子:

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

public class Animal { }
public class Girafee : Animal { }
public class Zebra : Animal { }

这将在运行时抛出ArrayTypeMismatchException

R#基本上暗示了一个可能的问题,即您将string[]分配给object[]这是编译器完全允许的,但可能会导致运行时异常,如果一个共享相同基类的对象被分配给已指向不同类型的数组(在我的示例中,我们实际指向girafee数组)。数组协方差被打破,意思是它不能为您提供泛型的编译时安全性。

Eric Lippert在Covariance and Contravariance in C#, Part Two: Array Covariance中讨论了这个问题:

  

不幸的是,这种特殊的协方差被打破了。它是   添加到CLR,因为Java需要它和CLR设计者想要的   能够支持类似Java的语言。然后我们将其添加到   C#因为它在CLR中。这个决定很有争议   时间和我对此并不是很满意,但我们无能为力   现在就做。

     

为什么会这样?因为放一只乌龟应该是合法的   成一群动物。使用语言中的数组协方差和   运行时你无法保证动物数组可以接受   龟,因为后备存储实际上可能是一个数组   长颈鹿。