2010-08-18 40 views
7

我很難理解爲什麼C#中的數組是協變的,並且這個協方差可以帶來什麼好處。考慮以下瑣碎的代碼示例:爲什麼C#數組是協變的,它帶來了什麼好處?

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

該代碼將編譯好的,但會毫不客氣地也許並不奇怪,在運行時發生爆炸。

如果我試圖嘗試使用泛型的相同的東西,編譯器會抱怨我,我會在早期階段意識到我的愚蠢,所以我的問題是這樣的:爲什麼C#編譯器允許與數組的協方差,潛在的好處是什麼?

回答

12

Eric Lippert說:

U不幸的是,這種特殊的協變性被打破了。它被添加到CLR是因爲Java需要它,而CLR設計者希望能夠支持類似Java的語言。然後,我們將它添加到C#中,因爲它在CLR中。這個決定當時頗具爭議,我對此並不滿意,但現在我們無能爲力。

4
+3

mquander贏得引用博客而不是僅僅鏈接到它。 – 2010-08-18 21:00:46

+1

@Jon B - 並引用_relevant_位。 – Oded 2010-08-18 21:02:01

+0

感謝您獲取更多信息的鏈接。很有用。 – nukefusion 2010-08-19 15:41:22

1

在許多情況下,代碼將在陣列的插槽之間移動或複製項目。假設Arr是一個具有至少兩個元素的一維數組,則無論Arr或其中包含的元素的類型如何,以下代碼都可以工作。

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

此代碼將是低效的,如果Arr爲值類型,但由於temp被讀出的陣列中,陣列的類型是保證能夠保持這樣的值。代碼將不得不boxbox和unbox value-type元素,因此對於這些類型來說效率很低,但它無論如何都會起作用。

請注意,雖然使數組協變是允許排序方法在任意數組類型上工作的一種方法,但它不是唯一的方法。另一種方法是讓System.Array包含一些方法和屬性,它們的參數與底層元素類型無關。例如,它可能包括一些簡單的方法,如Swap,CopyItemRoll,以及可能的方法來執行更復雜的排列給定的索引列表。請注意,與上面顯示的代碼不同,像Int[]這樣的類型可以以避免裝箱和取消裝箱的方式覆蓋其Swap方法。

相關問題