Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IEnumerable到IReadOnlyCollection_C#_.net_Generics_Casting - Fatal编程技术网

C# IEnumerable到IReadOnlyCollection

C# IEnumerable到IReadOnlyCollection,c#,.net,generics,casting,C#,.net,Generics,Casting,我有IEnumerable,需要将其作为参数传递给方法,但此方法采用IReadOnlyCollection 是否可以将IEnumerable转换为IReadOnlyCollection?一种方法是构造一个列表,并调用它: IReadOnlyCollection rdOnly=orig.ToList().AsReadOnly(); 这将生成,它实现了IReadOnlyCollection 注意:由于List也实现了IReadOnlyCollection,因此对AsReadOnly()的调用是可选

我有
IEnumerable
,需要将其作为参数传递给方法,但此方法采用
IReadOnlyCollection


是否可以将
IEnumerable
转换为
IReadOnlyCollection

一种方法是构造一个列表,并调用它:

IReadOnlyCollection rdOnly=orig.ToList().AsReadOnly();
这将生成,它实现了
IReadOnlyCollection


注意:由于
List
也实现了
IReadOnlyCollection
,因此对
AsReadOnly()
的调用是可选的。虽然可以使用
ToList()
的结果调用您的方法,但我更喜欢使用
AsReadOnly()
,这样代码的读者就会看到我调用的方法无意修改我的列表。当然,他们可以通过查看我正在调用的方法的签名来发现同样的问题,但是很高兴能够明确地说明这一点。

作为dasblinkenlight答案的替代方案,为了防止调用方强制转换到列表,而不是执行
orig.ToList().AsReadOnly()
,以下操作可能更好:

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

方法调用的数量相同,但其中一个将另一个作为参数,而不是对返回值进行调用。

由于其他答案似乎指向将集合包装为真正的只读类型,所以让我添加这一点

我很少看到调用方如此害怕
IEnumerable
-获取方法可能恶意尝试将该
IEnumerable
转换回
列表或其他可变类型,并开始对其进行变异。提示风琴音乐和邪恶的笑声

不可以。如果您正在使用的代码非常合理,那么如果它要求的类型仅具有读取功能(
IEnumerable
IReadOnlyCollection
…),它将只读取

使用
ToList()
并完成它。

作为旁注,如果您正在创建有问题的方法,通常最好只要求一个
IEnumerable
,表示您“只需要读取一组项目”。您是否需要它的
计数
,或者是否需要多次枚举它,这是一个实现细节,当然很容易更改。如果需要多个枚举,只需执行以下操作:

items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
items=作为IReadOnlyCollection的项目??items.ToList();//避免多重枚举
这将保持职责所在(尽可能在本地)和方法签名的干净


另一方面,当返回一组项目时,我更喜欢返回
IReadOnlyCollection
。为什么?目标是给来电者一些满足合理期望的东西——不多也不少。这些期望通常是集合被具体化,并且
计数
是已知的-这正是
IReadOnlyCollection
提供的(而简单的
IEnumerable
不提供的)。由于没有比这更具体,我们的契约符合预期,并且该方法仍然可以自由更改基础集合。(相比之下,如果一个方法返回一个
列表
,它会让我想知道我应该索引到列表中并对其进行修改的上下文是什么……答案通常是“无”。

.AsReadOnly()
确实有它的用途。如果您只返回
List
有人可以执行
rdOnly is IList
操作,它将返回
true
,如果您执行
.AsReadOnly()
操作,它将返回
false
。如果我不知道我的消费者是否可能尝试将我的结果强制转换为可变接口,我通常会在返回结果之前执行
.AsReadOnly()
。@ScottChamberlain这是一个非常重要的安全功能!你能调用
.ToArray()
而不是
.ToList().AsReadOnly()
?@MassDotNet你能,因为数组实现
IReadOnlyCollection
。我想是的——这就是我已经在做的。我只是想确保这样做不会引起任何错误行为(例如,打乱排序顺序)。这可能会更快@florien为什么会更快?你能解释一下吗?@snr嗯,老实说,我不能用一个合理的解释来支持它。不知何故,我相信这里唯一的区别在于类型是首先转换为数组还是列表,数组和使用数组的方式更容易集成到语言中,而且由于集合是不可更改的,所以列表在这里没有优势。尽管编译器确实可以对这一切进行优化。
items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration