我很难理解为什么C#中的数组是协变的,以及这种协变能带来什么好处。考虑下面这个简单的代码示例:
object[] myArray = new string[1];
myArray[0] = 1;
这段代码可以正常编译,但会在运行时突然爆炸,这也许并不令人意外。
如果我尝试使用泛型做同样的事情,编译器会对我发牢骚,我会在早期阶段意识到我的愚蠢,所以我的问题是:为什么C#编译器允许数组的这种协变,而且,潜在的好处是什么?
发布于 2010-08-19 04:59:49
Eric Lippert说:
不幸的是,这种特殊的协方差被打破了。之所以将它添加到CLR中,是因为Java需要它,而CLR设计者希望能够支持类似Java的语言。然后,我们将其添加到C#中,因为它在CLR中。这一决定在当时很有争议,我对此并不是很高兴,但现在我们对此无能为力。
发布于 2010-08-19 04:59:30
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
发布于 2013-07-16 02:23:00
在许多情况下,代码将在数组的插槽之间移动或复制项。如果Arr
是至少包含两个元素的一维数组,则无论Arr
的类型或其中包含的元素是什么,下面的代码都可以工作。
Object temp = Arr[1];
Arr[1] = Arr[0];
Arr[0] = temp;
如果Arr
是一个值类型,那么这个代码的效率会很低,但是因为temp
是从数组中读出的,所以可以保证数组的类型能够保存这样的值。代码将不得不装箱和拆箱值类型的元素,因此对于这种类型的效率将很低,但它仍然可以工作。
请注意,虽然使数组协变是允许排序方法在任意数组类型上工作的一种方法,但这并不是唯一的方法。另一种方法是让System.Array
包含一些方法和属性,这些方法和属性的参数与底层元素类型无关。例如,它可以包括一些简单的方法,如Swap
、CopyItem
和Roll
,还可能包括在给定一系列索引的情况下执行更复杂的排列的方法。请注意,与上面显示的代码不同,像Int[]
这样的类型可以通过某种方式重写其Swap
方法,以避免装箱和取消装箱。
https://stackoverflow.com/questions/3516619
复制相似问题