使用IReadOnlyCollection <t>而不是IEnumerable <t>来获取参数以避免可能的多次枚举

时间:2016-12-21 13:44:33

标签: c# resharper .net-4.5 ienumerable readonly-collection

我的问题与this one有关IEnumerable<T> vs IReadOnlyCollection<T>的使用有关。

我也总是使用IEnumerable<T>将集合作为返回类型和参数公开,因为它既可以不可变又可以延迟执行。

但是,我越来越关注代码中地点的增加,我必须枚举一个参数,以避免ReSharper给出的可能的多个枚举警告。我理解为什么ReSharper建议这一点,我同意它建议的代码(下面)以确保封装(即,没有关于调用者的假设)。

 Foo[] arr = col as Foo[] ?? col.ToArray();

但是,我发现此代码的重复性是污染性的,并且我同意某些来源IReadOnlyCollection<T>是更好的选择,尤其是this article中提出的要点,其中指出:

  

最近,我一直在考虑回归的优点和缺点   IEnumerable<T>

     

从好的方面来说,它与接口一样小,所以它   让你作为方法作者比提交更灵活   较重的替代方案,如IList<T>或(heaven forbid)数组。

     

但是,正如我在the last post中所述,IEnumerable<T>返回   诱使来电者违反Liskov Substitution Principle。它太   他们很容易使用Last()Count()等LINQ扩展方法,   其语义IEnumerable<T>不承诺。

     

需要更好的方法来锁定返回的集合   没有让这种诱惑如此突出。 (我想起了巴尼   Fife努力学习这一课。)

     

在.NET 4.5中输入新的IReadOnlyCollection<T>。它只增加了一个   属性IEnumerable<T>Count属性。通过承诺计数,   你保证你的呼叫者你的IEnumerable<T>确实有一个   总站。然后,他们可以使用像Last()这样的LINQ扩展方法   清醒的良心。

但是,正如观察者可能已经注意到的那样,本文仅讨论如何使用IReadOnlyCollection<T>作为返回类型。我的问题是,相同的论点同样适用于将其用于参数吗?任何关于此的理论思考或评论也将受到赞赏。

事实上,我认为使用IReadOnlyCollection<T>的一般经验法则是,如果使用IEnumerable<T>,可能会有多次枚举(相对于ReSharper警告)。否则,请使用IEnumerable<T>

1 个答案:

答案 0 :(得分:5)

在进一步考虑之后,我得出结论,根据我在我的问题中提到的文章,确实可以使用IReadOnlyCollection<T>作为参数,但仅限于它肯定会有的功能列举一下。如果枚举是基于其他参数,对象状态或工作流的条件,那么它仍然应该作为IEnumerable<T>传递,以便在语义上确保延迟评估。