Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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<;T>;_C#_.net_Collections_Ienumerable - Fatal编程技术网

C# 何时返回IEnumerable<;T>;

C# 何时返回IEnumerable<;T>;,c#,.net,collections,ienumerable,C#,.net,Collections,Ienumerable,我是否应该仅在惰性计算的情况下从方法和属性返回IEnumerable 返回IEnumerable时是否有任何模式,ICollection和IList?如果方法的调用者认为结果是只读的,则返回IEnumerable。只要调用者只需要从头到尾迭代集合,我就会返回IEnumerable。通过使用尽可能少的接口,我可以确保调用代码不会过于紧密地耦合,从而使以后更容易在方法或属性中更改代码。如果它仍然返回IEnumerable,其他人就不必关心了。如果之前它返回了List,而新方法在内部使用HashSet

我是否应该仅在惰性计算的情况下从方法和属性返回
IEnumerable


返回
IEnumerable
时是否有任何模式,
ICollection
IList

如果方法的调用者认为结果是只读的,则返回
IEnumerable

只要调用者只需要从头到尾迭代集合,我就会返回IEnumerable。通过使用尽可能少的接口,我可以确保调用代码不会过于紧密地耦合,从而使以后更容易在方法或属性中更改代码。如果它仍然返回IEnumerable,其他人就不必关心了。如果之前它返回了List,而新方法在内部使用HashSet表示事物,那么突然之间,许多其他事物也必须改变

因此,我总是喜欢返回集合接口,而不是具体的集合,除非调用代码确实需要知道它所处理的集合类型。我考虑调用方需要做的操作,找到支持它们的最小接口。

作为经验法则:

如果我确定自己始终知道返回的结果数量,我将返回
I收集
。如果调用方只是枚举,那么不管怎样,他们都可以轻松地将is视为
IEnumerable
。如果元素的顺序不是随机的,我使用
IList
。我在其他情况下使用
IEnumerable
。对于一个接口的不同实现,我使用“最松散”的接口,而不是重新复制结果,以满足特定的集合接口。

通常,如果它是一个列表(不是惰性),我会返回IList。比如说,当我的方法希望返回结果作为集合时,我总是这样做。 我之所以这样做,是因为它在方法签名中明确指出它是一个已加载的列表,而不是一个已惰性计算的列表,但使用接口不会公开具体类型(数组、列表、只读列表等)

当我对传入的集合执行任何类型的转换时,返回IEnumerable(LINQ方法)

同时,我在方法中使用IEnumerable作为参数,只是为了说明“这个函数不重要,它只需要能够通过”。当然,我确保IEnumerable在我的函数中只枚举一次

在以下情况下,应返回IEnumerable:

  • 结果无论是数组、列表还是任何类型的集合,都无关紧要,因为消费者只需要迭代它

  • 结果是使用
    IEnumerable
    的实现进行类型化的,但公共API并不强制使用者使用特定于API的类型,因此使用者保持中立使用

  • 如果结果预期为集合,则应返回
    IEnumerable
    的具体实现,如
    ICollection
    IList
    List
    等。消费者应该能够使用索引器访问可枚举成员,或者他们应该修改集合本身(添加、更新、删除、搜索集合中的项目)。

    在属性和返回类型的键入中选择正确的具体化更多地是关于一个好的案例分析,并且只键入您的消费者需要的内容

    例如,从概念上讲,某些属性应该返回一个列表,但使用者不应该修改它,因此,此属性应该返回一个列表,但您可以将其键入为
    IList


    正如我上面所说的,良好的案例分析并保持简单。

    这个答案没有解决迭代器方法与普通方法以及优点和考虑的核心问题。如果我返回新列表,那么我不在乎它是否为只读。我的意思是,我返回的新列表不是任何对象的成员。因此,您可以使用另一个枚举器包装任何类型的集合,以确保集合是真正的只读集合(假定它们的元素是不可变的),而不仅仅是返回它,不是吗?@Mudu:不是。实际上,我大部分时间都返回一个
    列表。因此,如果有人想把它列入名单,他可以。这一切都与通信有关:通过返回一个
    IEnumerable
    ,我告诉大家,结果应该只被迭代,而不应该被更改。这对于财产来说尤其如此。@RobLevine:我不明白。想把你的评论扩大一点吗?当你提到一个
    迭代器方法时,你是什么意思?
    ?你在下面的链接中有你的答案:@Serge,Ravia-OP的惰性评估标准使它与其他链接有细微的不同。@StuartLC是正确的,这个问题不应该作为重复问题来结束,因为这个问题不是以惰性评估为中心的(延迟执行)。然而,这个问题有一个答案,它对延迟执行做了更多的阐述()。有关延迟执行的更多信息,请参阅,但返回IEnumerable是一种特殊情况-它改变了返回到迭代器方法的行为-我认为这就是OP的目的。@Matthew,如果您正在编写供其他开发人员使用的代码,则不清楚他们将如何使用它,他们是需要迭代还是需要知道计数等。Rob,是的,这有时会导致问题,但我倾向于让调用方在需要时通过急切地枚举返回来处理它(但是,我也是Haskell程序员)Danil,我的措辞很糟糕,可能是因为该方法的作者也会影响调用者对该方法的使用。