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

Neo*_*Neo 10 c# resharper ienumerable readonly-collection .net-4.5

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

我也经常习惯IEnumerable<T>将集合作为返回类型和参数公开,因为它既可以是不可变的,也可以是懒惰的.

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

 Foo[] arr = col as Foo[] ?? col.ToArray();
Run Code Online (Sandbox Code Playgroud)

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

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

从积极的一面,它大约是最小的一个接口获得,所以给人们留下你的方法作者比承诺更重的替代需要更多的灵活性IList<T>或(但愿)阵列.

但是,正如我在一篇文章中所概述的那样,IEnumerable<T>回归诱使来电者违反Liskov替代原则.这太容易让他们使用LINQ扩展方法,如Last()Count(),其语义IEnumerable<T>不答应.

我们需要的是一种更好的方法来锁定一个返回的集合,而不会让这种诱惑如此突出.(我想起Barney Fife艰难地学习这一课.)

IReadOnlyCollection<T>在.NET 4.5中输入new.它只添加一个属性IEnumerable<T>:Count属性.通过承诺计数,你向你的来电者保证你IEnumerable<T>确实有一个终点.然后,他们可以使用LINQ扩展方法,如Last()清醒的良心.

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

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

Neo*_*Neo 5

在进一步考虑之后,根据我在我的问题中提到的文章,我得出的结论是,确实可以IReadOnlyCollection<T>用作参数,但仅限于必须枚举的函数.如果枚举是基于其他参数,对象状态或工作流的条件,则仍应传入它,IEnumerable<T>以便在语义上确保延迟评估.