IEnumerable到IReadOnlyCollection

时间:2015-08-21 04:17:50

标签: c# .net generics casting

我有IEnumerable<Object>,需要将方法作为参数传递,但此方法需要IReadOnlyCollection<Object>

是否可以将IEnumerable<Object>转换为IReadOnlyCollection<Object>

3 个答案:

答案 0 :(得分:28)

一种方法是构建一个列表,并在其上调用AsReadOnly()

IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();

这会生成ReadOnlyCollection<object>,它会实现IReadOnlyCollection<Object>

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

答案 1 :(得分:2)

作为dasblinkenlight的答案的替代方案,为防止来电者投射到列出&lt; T&gt; ,而不是orig.ToList().AsReadOnly(),以下情况可能更好:

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

这是相同数量的方法调用,但是一个将另一个作为参数而不是在返回值上调用。

答案 2 :(得分:1)

由于其他答案似乎都朝着将集合包装为真正只读类型的方向,因此让我添加一下。

我很少(如果有过)见过这样的情况,即呼叫者非常害怕,以至于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>,这让我想知道应该在哪个上下文中索引到列表并对其进行突变……而答案通常是“无”。)