2011-02-16 537 views
1

我創建了一個類,MonitoredCollection<T>時不再工作,基本上封裝/模擬名單,但可以讓我開槍某些呼叫事件。接口使用自定義集合類

然而現在,徘徊無論有一個參數,需要一個MonitoredCollection,其中T是一個接口,我不能再通過一個MonitoredCollection<T>其中T是實現該接口的類,如我可以用List

我一直以爲接口是一個語言「功能」,因此,我並不需要實現更多的東西來支持這一點,所以你有什麼我錯過了?

編輯:對不起,我在這個問題犯了一個錯誤,因爲若昂正確地指出,名單在這種情況下從來沒有做過這樣的問題是因爲它代表的是沒有!

+1

你是如何定義集合類的約束?我們可以看到一些代碼嗎? – 2011-02-16 20:27:51

+3

正如旁註;檢查出ObservableCollection ,因爲它可能提供您所需的行爲已經 – 2011-02-16 20:28:52

+2

正如評論,這個答案由Eric Lippert吹了我的腦海,可能會幫助你:http://stackoverflow.com/questions/4923936/c-casting-a-generic - 元素類型向下 – 2011-02-16 20:46:30

回答

3

假設您有一個MonitoredCollection<SomeObject>實例,並且您想將其視爲MonitoredCollection<ISomeInterface>實例,其中SomeObject事實上實際上實現了ISomeInterface。這對於從集合中檢索項目不會產生任何問題,因爲SomeObject類型的對象可以轉換爲接口類型ISomeInterface

但是,對於集合中用於修改集合的所有方法,例如爲集合指定新值或向集合中插入新項目的操作,此類集合創建了一整套問題。我會假設你的MonitoredCollection<SomeObject>實例有一個方法,如Add(SomeObject obj),它會在集合中插入一個新的對象。演員之後,此方法的簽名將爲Add(ISomeInterface obj)。這似乎是有道理的,但不是所有的對象都是必需的SomeObject實例。

由於鑄造對象將允許在收集原始對象不會允許操作,運行時不會允許這種轉換。 C#4.0引入了協變和逆變來明確說明這種類型轉換的有效性,你可以研究它們以解決這個問題。然而,你真的只會對你的集合的只讀版本有運氣(想想List<T>.AsReadOnly())。

1

不幸的是,你不能這樣做,有一個列表無論是。編譯器仍然無法轉換類型。你需要使用一個通用的方法。見下面的代碼:

class Test 
{ 
    void DoTest() 
    { 
     MonitoredList<IInterface> mlist1 = new MonitoredList<Inherited>(); //Error 
     MonitoredList<Inherited> mlist2 = new MonitoredList<Inherited>(); 
     DoSomething1(mlist2); //Error converting MonitoredList<Inherited> to MonitoredList<IInterface> 

     MonitoredList<IInterface> list1 = new MonitoredList<Inherited>(); //Error 
     MonitoredList<Inherited> list2 = new MonitoredList<Inherited>(); 
     DoSomething2(list2); //Error converting List<Inherited> to List<IInterface> 

     DoSomething3<Inherited>(mlist2); //Works fine 
     DoSomething3(mlist2); //<Inherited> is redundant 
    } 

    void DoSomething1(List<IInterface> list) 
    { } 

    void DoSomething2(MonitoredList<IInterface> list) 
    { } 

    //Generic method 
    void DoSomething3<T>(MonitoredList<T> list) where T : IInterface 
    { } 
} 

interface IInterface { } 

class Inherited : IInterface { } 

class MonitoredList<T> { }