2015-07-09 35 views
2

所以在我的班級,我有這個私人只讀會員ICollection<IMusicItem> playlist。我寧願使用接口ICollection<T>ICollection <T>沒有AddRange,但列表<T>沒有,正在鑄造壞

我想用List<T>.AddRange(IEnumerable<T> items)。在我的方法中,即使我在構造函數中將ICollection<T>實例化爲new List<T>(),它也會是危險ICollection強制轉換爲List<T>

這是不好的做法,有沒有更好的方法來做到這一點?

或者只是最好有一個List<T>

+0

也許使用擴展方法,就像在[這個SO答案](http://stackoverflow.com/a/1667634/996081)? – cubrr

+0

你可以爲任何'T'集合創建一個擴展方法'AddRange'。一個通用的。 – AgentFire

+5

你有什麼理由堅持**私人**成員的接口類型,特別是當你實例化一個具體的類型,可以讓你做你想做的事嗎? – nodots

回答

2

這並不危險(如果完成的話),毫無意義。

if (playlist is IList<IMusicItem>) 
{ 
    (playList as IList<IMusicItem>).AddRange(items); 
} 
else 
{ 
    // still need a foreach here 
} 

真正的問題是「我更喜歡使用接口ICollection<T>」。

爲什麼?你的問題表明它總是一個List,那麼爲什麼不把它公開呢?

將它作爲更一般的ICollection<>公開,只有當List以外的其他實現可能存在時纔有意義,然後該投射是無用的。

+1

是的,那就是我在找的東西。所以我的理解是,向客戶展示接口,但內部只使用具體的實現。 –

4

這是不好的做法,因爲它打破封裝。使用接口是好的,但如果必須將對象轉換回具體類型,則毫無意義。就好像你不知道具體類型一樣,或者如果你以後決定切換到另一種類型,它將會等待發生。

使用擴展方法代替:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items) 
{ 
    foreach (var item in items) 
     collection.Add(item); 
} 

注:這是更好地暴露接口,一個公共的API,因此您可以自由隨後更改執行對象,但它是一個風格問題是否做到這一點在私人領域。你也可以使用具體的類。

+0

我打算這麼做 –

+3

請注意,這會明顯降低'LIst.AddRange'的性能,因爲'List.AddRange'可以防止支持數組的多種大小調整,與此方法不同。 – Servy

+0

@Servy,這是真的,但只有*如果*項目是ICollection ',在這種情況下'列表。AddRange爲新項目分配一個數組,然後將其填充到序列中,然後將其複製回列表中,以便獲得2份數據副本。 –