为什么 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 是关于什么的,我能做些什么来缓解它的疑虑?
如果只是通用列表可能包含不良数据,我不会担心 - 如果出现问题,很容易追踪问题。
该方法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中。这一决定在时间,我对此不是很满意,但我们无能为力现在就去做吧。
为什么会这样坏?因为放一只应该永远是合法的变成一系列动物。语言中的数组协方差和运行时,您无法保证动物数组可以接受,因为后备存储实际上可能是一个数组长颈鹿。