为什么 Resharper 说,“从 string[] 到 object[] 的协变数组转换可能会导致写入操作运行时异常

本文关键字:转换 运行时 异常 操作 数组 Resharper string 为什么 object | 更新日期: 2023-09-27 18:20:40

此代码:

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 变成类似抱怨,"从 string[] 到 object[] 的协变数组转换可能会导致写入操作出现运行时异常"。

实际上,这段代码运行良好 - 组合框中填充了月份值; Resharper 是关于什么的,我能做些什么来缓解它的疑虑?

如果只是通用列表可能包含不良数据,我不会担心 - 如果出现问题,很容易追踪问题。

为什么 Resharper 说,“从 string[] 到 object[] 的协变数组转换可能会导致写入操作运行时异常

该方法comboBoxMonth.Items.AddRange需要一个object[]参数。 months.ToArray() string[].从 string[] 转换为 object[] 是有效的,但如果该方法尝试修改数组的元素,则会收到运行时错误。在这种情况下,它不会,因此您可以忽略警告。

如果它惹恼了你,你可以使用ToArray<object>()

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

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

演示问题的示例:

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在C#中的协方差和逆变中谈到了这一点,第二部分:数组协方差:

不幸的是,这种特殊的协方差被打破了。它是添加到 CLR 中是因为 Java 需要它,而 CLR 设计人员想要能够支持类似Java的语言。然后我们上去把它添加到C#,因为它在CLR中。这一决定在时间,我对此不是很满意,但我们无能为力现在就去做吧。

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