为什么C#数组是协变的,它带来了什么好处?

时间:2010-08-18 20:57:15

标签: c# arrays covariance

我无法理解为什么C#中的数组是协变的,以及这种协方差带来的好处。请考虑以下简单的代码示例:

object[] myArray = new string[1];
myArray[0] = 1;

这段代码可以正常编译,但是会毫不客气地,并且在运行时可能会毫不奇怪地爆炸。

如果我尝试使用泛型尝试同样的事情,编译器会抱怨我,我会在早期意识到我的愚蠢,所以我的问题是:为什么C#编译器允许这种与数组的协方差,此外,有什么潜在的好处?

3 个答案:

答案 0 :(得分:13)

Eric Lippert说:

  

不幸的是,这种特殊的协方差被打破了。它被添加到CLR中,因为Java需要它,而CLR设计者希望能够支持类似Java的语言。然后我们将它添加到C#,因为它在CLR中。这个决定在当时颇具争议,我对此并不十分满意,但现在我们无能为力。

答案 1 :(得分:4)

Eric Lippert有一篇关于此的文章(实际上是一个关于'变异'的长篇系列,我认为有11个部分)

http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx

还有一些更有意思的东西

http://blogs.msdn.com/b/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed-arrays-inconsistent.aspx

答案 2 :(得分:1)

在许多情况下,代码将在数组的插槽之间移动或复制项目。如果Arr是具有至少两个元素的一维数组,则无论Arr的类型或其中包含的元素如何,以下代码都将起作用。

Object temp = Arr[1];
Arr[1] = Arr[0];
Arr[0] = temp;

如果Arr是值类型,则此代码效率低,但由于从数组中读取temp,因此保证数组的类型能够保存这样的值。代码必须使用box和unbox值类型元素,因此使用这些类型效率低下,但无论如何都可以使用。

请注意,虽然使数组协变是允许排序方法在任意数组类型上工作的一种方法,但它并不是唯一的方法。另一种方法是让System.Array包含一些方法和属性,其参数与底层元素类型无关。例如,它可以包括一些简单的方法,如SwapCopyItemRoll,以及可能的方法,在给定索引列表的情况下执行更复杂的排列。请注意,与上面显示的代码不同,类似Int[]的类型可以覆盖其Swap方法,以避免装箱和拆箱。