2010-11-15 78 views
2

我試圖解決在C#中返回類型協方差的支持不足的問題,如this問題及其前兩個答案中所述。大多數情況下,我在設置演員時沒有任何問題,但是使用對象/接口列表的一個屬性妨礙了我的努力。之間的列表<MyType>和列表之間施展<IMyType>

我需要做什麼才能使IFoo.manyBars的演員陣容工作?

public interface IBar 
{ 
} 

public interface IFoo 
{ 
    IBar aBar { get; set; } 
    IEnumerable<IBar> manyBars { get; set; } 
} 

class CBar : IBar 
{ 
} 

class CFoo : IFoo 
{ 
    public CBar aBar { get; set; } 


    //this cast works 
    IBar IFoo.aBar 
    { 
     get { return aBar; } 
     set { aBar = (CBar)value; } 
    } 

    public List<CBar> manyBars { get; set; } 

    //the compiler can't cast either of these 
    List<IBar> IFoo.manyBars 
    { 
     get { return (List<IBar>)manyBars; } 
     set { manyBars = (List<CBar>)value; } 
    } 
} 

回答

3

試試這個。如果不存在,您必須將using System.Linq;添加到源文件的頂部。

List<IBar> IFoo.manyBars 
{ 
    get { return manyBars.Cast<IBar>().ToList(); } 
    set { manyBars = value.Cast<CBar>().ToList(); } 
} 

注意,這將分配並複製上一個新的陣列中的每個接入的財產。如果這不是你想要的,你應該考慮一種替代方法,例如使用類型IEnumerable<IBar>公開財產。

使用List<IBar>也意味着有人可能會嘗試做anObject.manyBars.Remove(0)這將做絕對沒有存儲在anObject列表中,因爲返回一個副本。

+0

將我的界面切換到IEnumerable 不是問題,這樣做會避免使用Linq來執行強制轉換結果的問題。 – 2010-11-15 21:06:17

+0

- 類的用戶將無法刪除項目,因爲'IEnumerable '接口暴露無刪除機制。所以對用戶而言,它會*不會令人驚訝,因爲他們甚至不能*嘗試*刪除項目。 – cdhowie 2010-11-15 21:12:38

+0

我想我可以忍受,因爲IFoo/IBar消費者就是我想要封裝的東西,並且向接口添加/刪除方法似乎不會造成任何主要問題。 CFoo和COtherFoo應用程序的其餘部分可以繼續使用列表 /列表版本。 – 2010-11-15 21:22:31

0

根據您的需求,您可以返回創建一個新的列表:

return new List<IBar>(manyBars); 

雖然記得,雖然對象是相同的,你會獲取不同的列表,讓你」我們需要小心添加/刪除列表中的對象。

+0

不幸的是,我的IFoo消費者需要能夠從列表中添加/刪除,因此創建新副本不是一個可行的選項。 – 2010-11-15 21:10:43

+0

好的,但要小心,因爲其他答案有同樣的問題。你可以將列表聲明更改爲「public List manyBars {get; set;}」? – 2010-11-15 21:24:18

+0

CBar和COtherBar都包含一些不共享的IBar用戶不關心的方法/屬性,所以我無法將CFoo/COtherFoo的定義更改爲使用列表,而無需添加將所有使用CFoo/COtherFoo對象的代碼庫的(更大)部分進行轉換。 – 2010-11-15 21:41:47

2

您可以複製:

get { return manyBars.OfType<IBar>().ToList(); } 
set { manyBars = value.Cast<CBar>().ToList(); } 

,但你不能施放該實例。如果你可以投射那個實例,當我嘗試Add一個不是CBar的IBar時會發生什麼。

+0

我知道這有些脆弱,但實際上CFoo/CBar和COtherFoo/COtherBar的用戶將被隔離。使用後者爲相關項目共享前者編寫的一段代碼是最後一刻的需求變更,因此我在尋求優雅方面受限於我的重構範圍。 – 2010-11-15 21:09:45

+0

好的,如果你想在出現問題時拋出Cast,請使用Cast。如果您想要過濾掉無效項目,請使用OfType。這幾乎是你唯一的選擇。 – 2010-11-15 22:12:48