【发布时间】:2016-11-11 22:10:42
【问题描述】:
LINQ 有 2 种计算可枚举的方法:Count 和 LongCount。实际上,这两者之间的唯一区别是第一个返回int,而第二个返回long。
我不清楚为什么要添加第二种方法。似乎它唯一的用例是处理超过 2B 个元素的枚举。出于以下几个原因,这对我来说似乎是一个糟糕的决定:
大多数 BCL 集合都由一维数组支持,这些数组的长度保证适合
int。试图超越这将引发OverflowException/OutOfMemoryException。LongCount是 O(n),因为IEnumerable是惰性的。如果您有一个可枚举的 3B 元素,则在其上调用LongCount,然后再次遍历它(如果您想使用任何值,则必须这样做),您将添加额外的 3B 迭代,这会非常慢,并且对开发者隐藏它。其他 LINQ 操作,例如
ToArray/ToList,不支持具有 2B+ 元素的枚举,因为 (1)。
我在这里遗漏了什么,还是添加了LongCount 有更实际的原因?谢谢。
【问题讨论】:
-
基于源代码
LongCount只是通过Enumerator.MoveNext迭代IEnumerable,而Count尝试将IEnumerable转换为ICollection并使用它的Count如果转换不成功它将以与LongCount相同的方式迭代IEnumerable。 https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,d76b4b5d3fd67767。基于@EricLipert 的这个“猜测”似乎非常合乎逻辑 -
@Fabio,这只是一个优化。
LongCount也检查ICollection并将结果转换为long在语义上是正确的,但LongCount的使用并不多,所以这就是他们没有费心这样做的原因。
标签: c# .net linq ienumerable linq-to-objects