IEnumerable到IReadOnlyCollection

Moh*_*adr 29 .net c# generics casting

我有IEnumerable<Object>并且需要传递给方法作为参数但是这个方法需要IReadOnlyCollection<Object>

有可能转换IEnumerable<Object>IReadOnlyCollection<Object>

das*_*ght 36

一种方法是构建一个列表,然后调用AsReadOnly()它:

IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();
Run Code Online (Sandbox Code Playgroud)

这产生ReadOnlyCollection<object>,实现IReadOnlyCollection<Object>.

注意:由于也是List<T>实现IReadOnlyCollection<T>,所以调用AsReadOnly()是可选的.虽然可以使用结果来调用你的方法,但ToList()我更喜欢使用AsReadOnly(),这样我的代码的读者就会看到我调用的方法无意修改我的列表.当然,通过查看我调用的方法的签名,他们可以找到相同的东西,但很明白它是明确的.

  • 你可以调用`.ToArray()`而不是`.ToList().AsReadOnly()`吗? (7认同)
  • `.AsReadOnly()` 确实有它的用途。如果你只返回`List&lt;T&gt;`,有人可以做一个`rdOnly is IList&lt;T&gt;`,它会返回`true`,如果你做`.AsReadOnly()`,它会返回`false`。如果我不知道我的消费者是否可能尝试将我的结果转换为可变接口,我经常在返回结果之前执行 `.AsReadOnly()`。 (4认同)

Tim*_*imo 5

由于其他答案似乎指向以真正只读类型包装集合的方向,让我补充一下。

我很少(如果有的话)看到调用者如此害怕以致于IEnumerable<T>-taking 方法可能会恶意尝试将其转换IEnumerable<T>回 aList或其他可变类型并开始对其进行变异的情况。提示器官音乐和邪恶的笑声!

不。如果您正在使用的代码甚至是合理的,那么如果它要求一种仅具有读取功能的类型(IEnumerable<T>, IReadOnlyCollection<T>...),它只会读取。

使用ToList()并完成它。

附带说明一下,如果您正在创建有问题的方法,通常最好不要超过 an IEnumerable<T>,表明您“只想阅读一堆项目”。您是否需要它Count或需要多次枚举它是一个实现细节,当然很容易改变。如果您需要多个枚举,只需执行以下操作:

items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
Run Code Online (Sandbox Code Playgroud)

这保持了它所属的责任(尽可能在本地)和方法签名干净。

另一方面,当返回一堆项目时,我更喜欢返回一个IReadOnlyCollection<T>. 为什么?目标是给来电者一些满足合理期望的东西——不多也不少。这些期望通常是集合是具体化的并且Count是已知的——正是IReadOnlyCollection<T>提供了什么(简单的IEnumerable<T>没有)。通过不比这更具体,我们的合约符合预期,并且该方法仍然可以自由更改基础集合。(相反,如果一个方法返回 a List<T>,它让我想知道我应该索引到列表中并改变它的上下文......答案通常是“无”。)