12

我的问题与这个有关IEnumerable<T>vs使用的问题有关IReadOnlyCollection<T>

我也一直习惯于IEnumerable<T>将集合公开为返回类型和参数,因为它受益于不可变和延迟执行。

但是,我越来越担心代码中必须枚举参数以避免 ReSharper 给出的可能的多重枚举警告的地方的扩散。我理解为什么 ReSharper 建议这样做,并且我同意它建议的代码(如下)以确保封装(即,不对调用者进行任何假设)。

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

但是,我发现此代码的重复性具有污染性,并且我同意一些IReadOnlyCollection<T>更好的替代方案,特别是本文中提出的观点,其中指出:

最近一直在考虑回国的利弊 IEnumerable<T>

从好的方面来说,它几乎与接口一样小,因此它为方法作者提供了比提交更重的替代方案(如IList<T>或(天堂禁止)数组)更大的灵活性。

但是,正如我在一篇文章中概述的那样,IEnumerable<T>返回会诱使调用者违反Liskov 替换原则。他们太容易使用 LINQ 扩展方法,如Last()and Count(),其语义IEnumerable<T>不承诺。

需要一种更好的方法来锁定退回的收藏品,而不会使这种诱惑如此突出。(我想起了巴尼·法夫(Barney Fife)艰难地学习这一课。)

输入IReadOnlyCollection<T>.NET 4.5 中的新功能。它只向IEnumerable<T>:属性添加了一个Count属性。通过承诺计数,您可以向呼叫者保证您IEnumerable<T>确实有一个终点站。然后他们可以Last()问心无愧地使用 LINQ 扩展方法。

然而,细心的人可能已经注意到,本文只讨论了使用IReadOnlyCollection<T>返回类型。我的问题是,相同的论点是否同样适用于将其用于参数?对此的任何理论想法或评论也将不胜感激。

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

4

1 回答 1

7

进一步考虑后,我根据我在问题中提到的文章得出结论,IReadOnlyCollection<T>作为参数使用确实是可以的,但仅限于肯定会被枚举的函数中。如果枚举基于其他参数、对象状态或工作流是有条件的,则仍应将其传入,IEnumerable<T>以便在语义上确保惰性求值。

于 2016-12-23T10:36:30.107 回答