2013-03-22 60 views
0

我有圓的物體(如圈實現IShape接口的數組和我有了的List<IShape>參數的函數。爲什麼我不能在我的圈子到此的數組傳遞?爲什麼.Net 4不允許我傳入一個接口數組?

視覺工作室給我生成錯誤的說法不能轉換List<Circle>List<IShape>

+2

你的意思是你有一個列表''和功能'美孚(名單 C)'和'圈:IShape'?考慮'Foo'是否有'c.Add(new Square())'這一行。 – 2013-03-22 02:44:25

+2

這是一個經常被問到的問題。搜索包含可枚舉類型的協方差的問題。 – 2013-03-22 02:44:49

+1

請問IEnumerable 夠用嗎?並非所有類型都是協變的。 – 2013-03-22 02:45:21

回答

5

簡短的回答是,因爲功能Foo可以實現這樣的:

void Foo(IList<IShape> c) 
{ 
    c.Add(new Square()); 
} 

如果你通過了List<Circle>Foo,所提供的類型將不能存儲Square,即使類型簽名聲稱它沒問題。 IList<T>不是covariant:一般IList<Circle>不能是IList<IShape>,因爲它不支持添加任意形狀。

修復方法是使用IEnumerable<IShape>來接受Foo中的參數,但這在所有情況下都不起作用。 IEnumerable<T>是協變:專門的IEnumerable<Circle>符合一般IEnumerable<IShape>的合同。


這種行爲也是一件好事。當它不應該是協變時,一個經典的例子是一個數組。下面的代碼可以編譯,但會在運行時失敗:

void Bar() 
{ 
    // legal in C#: 
    object[] o = new string[10]; 
    // fails with ArrayTypeMismatchException: can't store Int in a String[] 
    o[0] = 10; 
} 
+0

實際上,'IEnumerable '不會被具有參數'IEnumerable '的方法接受'',您必須將您傳遞給該函數的集合轉換爲如果方法簽名是'Foo(IEnumerable 形狀)''IEnumerable '的實例。 – 2013-03-22 03:53:55

+2

@ FrancisR.Griffiths-Keam,你錯了。從.NET 4開始,IEnumerable 與T是協變的,這意味着只要X派生自(或實現)T,IEnumerable 就可以被替換。 – 2013-03-22 04:07:37

+0

@AnthonyPegram Ahh我錯過了那個備忘錄,謝謝你的記錄。 – 2013-03-22 04:10:54

相關問題