IReadOnlyCollection的可枚举对象
本文关键字:对象 枚举 IReadOnlyCollection | 更新日期: 2023-09-27 18:09:06
我有IEnumerable<Object>
,需要传递给一个方法作为参数,但这个方法接受IReadOnlyCollection<Object>
能否将IEnumerable<Object>
转化为IReadOnlyCollection<Object>
一种方法是构造一个列表,并在其上调用AsReadOnly()
:
IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();
生成ReadOnlyCollection<object>
, IReadOnlyCollection<Object>
实现。
注意:由于List<T>
也实现了IReadOnlyCollection<T>
,所以对AsReadOnly()
的调用是可选的。虽然可以用ToList()
的结果调用您的方法,但我更喜欢使用AsReadOnly()
,这样我的代码的读者就会看到我调用的方法无意修改我的列表。当然,他们可以通过查看我正在调用的方法的签名来发现同样的事情,但最好是明确地说明它。
由于其他的答案似乎引导了用真正的只读类型包装集合的方向,让我添加这个
我很少(如果有的话)看到这样的情况:调用者非常害怕,以至于一个IEnumerable<T>
获取方法可能会恶意地试图将IEnumerable<T>
转换回List
或其他可变类型,并开始对其进行变异。风琴音乐和邪恶的笑声响起!
。如果你正在使用的代码是合理的,那么如果它要求的类型只有读取功能(IEnumerable<T>
, IReadOnlyCollection<T>
…),它将只读取。
使用ToList()
并完成它
作为旁注,如果您正在创建有问题的方法,通常最好要求不超过IEnumerable<T>
,表明您"只想要读取一堆项"。是否需要它的Count
,或者是否需要多次枚举它,这是一个实现细节,当然很容易发生变化。如果需要多个枚举,只需这样做:
items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
这使责任保持在它所属的位置(尽可能在本地),并且方法签名干净。
另一方面,当返回一堆项目时,我更喜欢返回IReadOnlyCollection<T>
。为什么?我们的目标是给打电话的人一些满足合理期望的东西——不多也不少。这些期望通常是实现了集合,并且Count
是已知的——正是IReadOnlyCollection<T>
提供的(而简单的IEnumerable<T>
不提供)。由于没有比这更具体,我们的契约符合预期,并且方法仍然可以自由地更改底层集合。(相比之下,如果一个方法返回一个List<T>
,它让我想知道有什么上下文,我应该索引到列表并改变它…而答案通常是"没有"。
作为dasblinkenlight的答案的替代方案,为了防止调用者强制转换到Listorig.ToList().AsReadOnly()
,以下可能更好:
ReadOnlyCollection<object> rdOnly = Array.AsReadOnly(orig.ToArray());
方法调用的次数相同,但其中一个方法将另一个方法作为参数,而不是在返回值时调用。