Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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 extensions中-为什么只有Count()针对ICollection进行了优化?_C#_Performance_Linq - Fatal编程技术网

C# 在IEnumerable extensions中-为什么只有Count()针对ICollection进行了优化?

C# 在IEnumerable extensions中-为什么只有Count()针对ICollection进行了优化?,c#,performance,linq,C#,Performance,Linq,在反编译LinqIEnumerable扩展方法之后,我很高兴看到 Count()方法在尝试迭代整个可枚举项之前,尝试将其向下转换为ICollection或ICollection,例如: 公共静态整数计数(此IEnumerable源){ if(source==null)抛出错误.ArgumentNull(“source”); ICollection collectionoft=源作为ICollection; 如果(collectionoft!=null)返回collectionoft.Count;

在反编译Linq
IEnumerable
扩展方法之后,我很高兴看到
Count()
方法在尝试迭代整个可枚举项之前,尝试将其向下转换为
ICollection
ICollection
,例如:

公共静态整数计数(此IEnumerable源){
if(source==null)抛出错误.ArgumentNull(“source”);
ICollection collectionoft=源作为ICollection;
如果(collectionoft!=null)返回collectionoft.Count;
ICollection collection=源作为ICollection;
if(collection!=null)返回collection.Count;
整数计数=0;
使用(IEnumerator e=source.GetEnumerator()){
检查{
而(e.MoveNext())count++;
}
}
返回计数;
}

为什么这不会发生在
Any()
中?使用
.Count>0
而不是创建数组枚举器是否会使它受益?

并非所有集合都提供对
Count
属性的O(1)访问。例如,访问的count属性为O(n)。因此,优化会使情况变得更糟,因此 不应该被称为优化

不仅
ConcurrentQueue
,几乎所有的并发集合(
ConcurrentDictionary
ConcurrentStack
等)都属于这一类


也许这就是他们决定不做这件事的原因。

不。代码的成本总是比任何可能的性能增益都要大,而性能增益几乎为零。不要忘记,LINQ的全部要点是链接一组这样的表达式,因此您最有可能将
Any
与谓词或它自己的一组过滤器等一起使用

在什么情况下,您会使用
Any
作为
Count
的替代方案?即使是
Count
优化在IMO中的使用率也很低-如果您在一些逻辑中使用
Count()
作为参数,而这些逻辑期望
IEnumerable
作为参数,那么您很可能做得不对-至少,您倾向于多次枚举可枚举项,这很可能会破坏某些东西或破坏您的性能:D

别忘了,一旦对可枚举数组执行任何操作,您就失去了“数组属性”,例如
类别。其中(i=>i.Name.StartsWith(“Hello”)).Count()
将不使用快捷方式


当然,在任何空的枚举表上使用一个枚举器的成本可能几乎是免费的。枚举数只是一个简单的结构,在数组上,也不会有任何昂贵的初始化。

如果源是
集合
,我相信
移动下一步
(在
任何
实现中仅在
If
中使用一次)与向下转换到
集合
并检查
计数
一样快。
ICollection
的计数方法可能比上述
Count
方法所采用的简单方法要快,但事实上它可能(例如,不存储计数的链接列表)实际上必须遍历整个数据结构才能生成计数。因此,与只访问集合中的第一个元素相比,您建议的优化可能是一个悲观的结果。@Damien_不信者起初,我想在我的回答中给出
LinkedList
作为一个例子,后来我意识到
LinkedList.Count
仅为O(1)。@SriramSakthivel-链接列表的计数为O(1)。任何人都可以自由地实现他们选择的任何数据结构,并将其标记为一个
ICollection
,我认为一个不存储单独计数的链表应该是大多数人都会想到的。当我看到你的答案(这与我的评论的观点几乎相同)时,我做了+1。我没有用它来代替
Count()
,有时我用它来表达更多的意思。正如在中一样,
array.Any()
array.Length>0
@Nitzankin可读性更好是的,但一旦它“更具表现力”,它就不再能够执行简单的
返回计数>0
。是的,它可以,只需尝试向下转换到ICollection,但是,正如@SriramSakthivel所述,事情变得不可预测,而且并不总是如此optimized@Nitzankin您可能会感兴趣,当我在一个简单的基准测试中尝试它时,
Any()
的速度大约是
Count()
的两倍,即使是在一个数组上——当然,这种差异其实并不重要,因为它可以每秒执行数百万次。这就是为什么您不应该猜测性能,而应该测试它的原因。因此,如果你想知道
IEnumerable
中是否有任何元素,请继续使用
Any
,除非你能证明
计数实际上比你的用例快得多。@Luaan:“在什么情况下,你可以使用Any作为计数的替代方法?”-如果你想知道
IEnumerable
中是否有任何元素
Count()>0
在某些情况下(例如ConcurrentQueue)会出现O(n)。我的朋友们,这是有原因的:——)投反对票,因为答案没有道理。当您将输入强制转换为List并检查“List.Count>0”条件时,您肯定可以提高任何()方法的性能,就像在Count()方法中所做的那样。@ChrisEelmaa-这里没有对
List
的强制转换-有些接口已经实现了与所寻求的语义完全匹配的成员。让扩展方法只处理BCL中的具体类型会有一点异味。@ChrisEelmaa不是很密集。我的回答是有道理的。你的评论毫无意义。问题是为什么在
Count
方法中添加了
ICollection
的优化没有添加到
Any
。好的,你说的是
列表
。关于
数组
?,关于
可观测集合
?还有所有的收藏品?您希望为每个应用程序添加if语句