2010-08-31 64 views
6

很明顯,T[]陣列類型不是covariant,因爲T[]的元素可以通過索引來設置。U []可以轉換爲T []嗎?

但是,只要U派生自TU[]就可以轉換爲T[],而不會受到編譯器的任何抱怨。

Man[] men = new[] { new Man("Aaron"), new Man("Billy"), new Man("Charlie") }; 
Person[] people = (Person[])men; 

在似乎menpeople似乎保持到同一Array對象的引用上面的代碼。設置men[0] = new Man("Aidan")的效果可以在people[0]處看到。同樣在運行時*嘗試people[0] = new Woman("Debbie")導致ArrayTypeMismatchException

這是否意味着T[]類型實際上會對每個set調用執行類型檢查?看起來,如果允許以這種方式投射數組,這一點是必須的。

我想我的問題只是:這怎麼可能?很明顯,U[]並非來自T[]。這也是對我來說不清楚我是否可以永遠定義我自己的類型,將以這種方式工作:實際上不變但行爲協變。


*雖然陣列方差顯然是由CLR允許的,任何語言可以禁止陣列類型之間進行鑄造。然而,看來這行爲是相同的在VB.NET:

Dim men = New Man() { New Man("Aaron"), New Man("Billy"), New Man("Charlie") } 
Dim people = CType(men, Person()) 
+1

你能用一種特定的語言標記這個,對於我們這些不知道你在說哪一個的人? – 2010-08-31 17:12:01

+0

@Philip:我*可以*,但它似乎同樣適用於VB.NET和C#。這就是爲什麼我只用.net標籤去。 – 2010-08-31 17:16:25

+0

語言不能完全禁止它 - 用語言X編寫的方法可以從語言Y接收共變數組。 – SLaks 2010-08-31 17:25:44

回答

7

這是陣列的特殊行爲,並且不能在任何其它類型的被複制。

It is generally regarded as a mistake

+1

那麼它如何與數組一起工作呢? – 2010-08-31 17:09:26

+1

@丹:CLR中的特殊魔法。是;每個數組集合(非密封類型)都會執行類型檢查。 – SLaks 2010-08-31 17:11:07

+0

@丹濤你看過鏈接的帖子嗎?這裏有解釋 – jeroenh 2010-08-31 17:14:11

2

這只是因爲它是CLR的一部分的特殊功能。即使技術上它們不是,數組自動協變。編譯器必須知道這一點並生成適當的類型檢查。

雖然有些人認爲這個功能是一個錯誤,但在類型安全集合和通用接口協方差之前是非常重要的。如果沒有它,你甚至無法編寫一個函數對數組進行排序。

+0

編譯器不需要知道這一點,除了投射規則。這由運行時處理。 – SLaks 2010-08-31 17:11:49

相關問題