我无法理解为什么C#中的数组是协变的,以及这种协方差带来的好处。请考虑以下简单的代码示例:
object[] myArray = new string[1];
myArray[0] = 1;
这段代码可以正常编译,但是会毫不客气地,并且在运行时可能会毫不奇怪地爆炸。
如果我尝试使用泛型尝试同样的事情,编译器会抱怨我,我会在早期意识到我的愚蠢,所以我的问题是:为什么C#编译器允许这种与数组的协方差,此外,有什么潜在的好处?
答案 0 :(得分:13)
不幸的是,这种特殊的协方差被打破了。它被添加到CLR中,因为Java需要它,而CLR设计者希望能够支持类似Java的语言。然后我们将它添加到C#,因为它在CLR中。这个决定在当时颇具争议,我对此并不十分满意,但现在我们无能为力。
答案 1 :(得分:4)
Eric Lippert有一篇关于此的文章(实际上是一个关于'变异'的长篇系列,我认为有11个部分)
还有一些更有意思的东西
答案 2 :(得分:1)
在许多情况下,代码将在数组的插槽之间移动或复制项目。如果Arr
是具有至少两个元素的一维数组,则无论Arr
的类型或其中包含的元素如何,以下代码都将起作用。
Object temp = Arr[1];
Arr[1] = Arr[0];
Arr[0] = temp;
如果Arr
是值类型,则此代码效率低,但由于从数组中读取temp
,因此保证数组的类型能够保存这样的值。代码必须使用box和unbox值类型元素,因此使用这些类型效率低下,但无论如何都可以使用。
请注意,虽然使数组协变是允许排序方法在任意数组类型上工作的一种方法,但它并不是唯一的方法。另一种方法是让System.Array
包含一些方法和属性,其参数与底层元素类型无关。例如,它可以包括一些简单的方法,如Swap
,CopyItem
和Roll
,以及可能的方法,在给定索引列表的情况下执行更复杂的排列。请注意,与上面显示的代码不同,类似Int[]
的类型可以覆盖其Swap
方法,以避免装箱和拆箱。