如果调用代码仅对集合进行迭代,是否有任何理由将内部集合公开为ReadOnlyCollection而不是IEnumerable?
class Bar { private ICollection<Foo> foos; // Which one is to be preferred? public IEnumerable<Foo> Foos { ... } public ReadOnlyCollection<Foo> Foos { ... } } // Calling code: foreach (var f in bar.Foos) DoSomething(f);
如我所见,IEnumerable是ReadOnlyCollection接口的子集,它不允许用户修改集合。因此,如果IEnumberable接口足够了,那就可以使用它。这是推理的正确方法,还是我错过了一些东西?
谢谢/ Erik
更现代的解决方案
除非您需要内部集合是可变的,否则可以使用该System.Collections.Immutable程序包,将字段类型更改为不可变集合,然后直接公开它- Foo当然,假设自身是不可变的。
System.Collections.Immutable
Foo
更新了答案以更直接地解决问题
这取决于您对调用代码的信任程度。如果您完全控制将调用此成员的所有内容,并且您 保证 不会使用任何代码:
ICollection<Foo> evil = (ICollection<Foo>) bar.Foos; evil.Add(...);
那么可以肯定的是,如果您直接将集合退回,则不会造成任何伤害。我通常会比这更偏执。
同样,正如您所说:如果只 需要 IEnumerable<T>,那么为什么将自己绑在更坚固的东西上?
IEnumerable<T>
原始答案
如果使用的是.NET 3.5,则可以通过使用对Skip的简单调用来避免进行复制 并 避免进行简单的转换:
public IEnumerable<Foo> Foos { get { return foos.Skip(0); } }
(还有很多其他选项可以用来进行简单包装-关于SkipSelect / Where的好处是,没有委托可以为每次迭代无意义地执行。)
Skip
如果您不使用.NET 3.5,则可以编写一个非常简单的包装器以执行相同的操作:
public static IEnumerable<T> Wrapper<T>(IEnumerable<T> source) { foreach (T element in source) { yield return element; } }