IReadOnlyCollection的可枚举对象

本文关键字:对象 枚举 IReadOnlyCollection | 更新日期: 2023-09-27 18:09:06

我有IEnumerable<Object>,需要传递给一个方法作为参数,但这个方法接受IReadOnlyCollection<Object>

能否将IEnumerable<Object>转化为IReadOnlyCollection<Object>

IReadOnlyCollection的可枚举对象

一种方法是构造一个列表,并在其上调用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的答案的替代方案,为了防止调用者强制转换到List,而不是执行orig.ToList().AsReadOnly(),以下可能更好:

ReadOnlyCollection<object> rdOnly = Array.AsReadOnly(orig.ToArray());

方法调用的次数相同,但其中一个方法将另一个方法作为参数,而不是在返回值时调用。