2015-07-09 99 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份数据副本。 –