2011-06-28 74 views
4

說我得到了這個接口:接口多態性在C#2.0

public interface IFoo 
{ 
    string Text {get;} 
} 

這個類實現它:

public class Bar : IFoo 
{ 
    public string Text 
    { 
     get {return "Hello World!";} 
    } 
} 

我有一個函數,作爲參數List<IFoo> 。當我嘗試將它傳遞一個List<Bar>,我得到這個編譯器錯誤:

Argument 1: cannot convert from System.Collections.Generic.List<Bar> 
to System.Collections.Generic.List<IFoo> 

這是爲什麼?看起來這應該是出於同樣的原因,就好像我傳遞了一個直接從Bar繼承的類的列表。

+0

嘗試使用泛型。然後你的函數可以把List 作爲參數。檢查出http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx向下滾動到通用方法的一半 – Gage

+0

雖然我需要傳遞來實現此接口的對象。如果我使用的是更新版本的.NET,我會很樂意使用泛型,並使用'Func'參數從我傳遞的對象中獲取所需的信息。 –

+0

根據文章我鏈接的泛型應該工作.net 2.0 – Gage

回答

10

Why is this? It seems like that should work for the same reason as if I passed a list of a class that inherits from Bar directly.

因爲這場災難可能發生:

class EvilBar : IFoo { } 

List<Bar> list = new List<Bar>(); 
List<IFoo> foos = list; // suppose it were allowed 
foos.Add(new EvilBar()); 

現在你已經添加EvilBar到列表不是隻能接受Bar。哎呀!

基本上,您已經發現T -> List<T>T中不是協變的。

+0

雖然這看起來不是問題。編譯器允許'List '轉換爲'List ',因爲'Bar'實現了'IFoo'。出於同樣的原因,它應該允許在實現IFoo的對象列表中添加一個EvilBar。不過,它不應該允許從列表轉換回List

+0

這是在更高版本的.NET中更改的嗎? –

+0

@Mr。傑斐遜:不,你不能做這樣一個從「列表」到「列表」的轉換。實際上該參考後​​面的對象仍然是一個'List ',即使列表''可以,它仍然不能接受'EvilBar'。這根本不可能。 – jason

4

由於.Net 2.0中不支持通用反轉換。你可以用數組來完成它。

IFoo[] foos = new Bar[5]; 

另一種選擇是做

List<IFoo> myList = myBarList.ConvertAll(b => (IFoo)b); 
+0

這種協變性被打破了,因爲我的答案中概述了這個原因。 – jason

+0

我將參數轉換爲一個數組,在傳遞的參數末尾添加'.ToArray()',編譯器很開心。 –

+0

@Mr。傑斐遜:這不安全! – jason

1

千萬不要錯過List<Bar>。使用演員表並通過此:

yourObj.YourMethod(yourListOfBar.Cast<IBar>().ToList()); 
+0

我想你的'Cast'方法是不存在於.NET 2.0中。否則,這將很好。 –

+1

哦,對。 .NET 2.0。可憐的傢伙,錯過了這麼多... :) –