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(),这样我的代码的读者就会看到我调用的方法无意修改我的列表.当然,通过查看我调用的方法的签名,他们可以找到相同的东西,但很明白它是明确的.
由于其他答案似乎指向以真正只读类型包装集合的方向,让我补充一下。
我很少(如果有的话)看到调用者如此害怕以致于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>,它让我想知道我应该索引到列表中并改变它的上下文......答案通常是“无”。)