2013-10-31 24 views
1

以下不能在線編譯fm.AddFoo(new StringFoo());與錯誤消息:無法轉換通用對象

參數1:無法從「ClassLibrary2.StringFoo」到「ClassLibrary2.IFoo」轉換

這似乎合乎邏輯的,因爲我從字符串對象繼承。

public interface IFoo<T> 
{ 
    void Handle(T value); 
} 

public class StringFoo : IFoo<string> 
{ 
    public void Handle(string value) 
    { } 
} 

public class ObjectFoo : IFoo<object> 
{ 
    public void Handle(object value) 
    { } 
} 

public class FooManager 
{ 
    private readonly List<IFoo<object>> _foos; 

    public FooManager() 
    { 
     _foos = new List<IFoo<object>>(); 
    } 

    public void AddFoo(IFoo<object> foo) 
    { 
     _foos.Add(foo); 
    } 
} 

public class Bad 
{ 
    public Bad() 
    { 
     var fm = new FooManager(); 

     fm.AddFoo(new StringFoo()); \\ This does not compile 
    } 
} 

感謝

+0

可能重複的[我可以創建一個泛型類型的字典?](http://stackoverflow.com/questions/654752/can-i-create-a-dictionary-of-generic-types) – CodeCaster

回答

1

儘管它可能看起來像的IFoo是的IFoo的子類,事實並非如此。當你關閉IFoo <>到一個特定的類型是不是從IFoo創建一個IFoo的子類時,它們是分離的,不同的類型,沒有共同的層次結構。

+0

哦,是的,我忘了這一切。謝謝! –

+0

明確地說,在上面的代碼中,「IFoo 」不是「IFoo 」。要做到這一點,就需要IFoo是協變的,但它的成員Handle卻是相反的。看到我的新答案。 –

1

如果你可以讓你的IFoo<>接口它的工作,那就是如果你被允許改變它的聲明爲:

public interface IFoo<out T> 

(注意out)。因爲使用協方差,任何IFoo<string>也將是IFoo<object>,因爲string是參考類型,並且源自object

但:IFoo<>一員,Handle方法,使用在逆變方式的類型的參數。所以你的界面不能聲明爲協變(out)。 (它可以被宣佈爲逆變(in),但是對於上面的示例而言,這種做法的方向錯誤)。

閱讀泛型中的協變和逆變。

這裏的根本問題是您的StringFoo只處理字符串。因此,它不能被用作IFoo<object>,因爲你可以通過例如Giraffe實例(Giraffeobject派生,所以Giraffeobject)到StringFoo,那是不可能的,當它Handle需要string