我最近看到一些代码的代码库和我一起工作,其中ReSharper的提供将它重构到collection.Any(Func< bool >)
我想了解一下这对性能的影响。 说我有一个电话,看起来像这样:
bool hasEvenValue = collection.Any(i => (i % 2) == 0);
...这看起来像此数据...
{ 1, 2, 3, 5, 3, 5, 1, 3, 5, 2 }
什么时候Enumerable.Any()返回值? 第二个数据元素,还是会返回true,在这种情况下之前处理每一个元素 ?
它尽快返回,因为它看到了一个匹配的元素,或者如果没有它处理的整个序列。
出于这个原因,它是比使用更好.Count(...) != 0
(也更具可读性和语义上有意义)。
下面是执行IEnumerable<T>.Any(...)
未编译与dotKeep):
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
throw Error.ArgumentNull("source");
if (predicate == null)
throw Error.ArgumentNull("predicate");
foreach (TSource source1 in source)
{
if (predicate(source1))
return true;
}
return false;
}
所以基本上,只要项目符合条件返回。
什么时候IEnumerable.Any(Func键)返回一个值?
总是立刻因为不推迟执行它时,它的执行。 它返回一个布尔其指示是否在序列中的元件中的一个在给定谓词返回true。 因此,它并不需要执行,不像整个查询Count
。
下面是一些代码,我在LINQPad刮起来说明的是, Any
运营商终止它击中后的首场比赛。
void Main()
{
Console.WriteLine("Are there any evens? " + YieldEvenThenThrowEnumerable().Any(i => i % 2 == 0));
Console.WriteLine("still running");
Console.WriteLine("Are there any odds? " + YieldEvenThenThrowEnumerable().Any(i => i % 2 == 1));
Console.WriteLine("never reaches this point");
}
IEnumerable<int> YieldEvenThenThrowEnumerable()
{
yield return 2;
throw new InvalidOperationException("TEST");
}
其输出:
是否有任何找齐?
真正
仍在运行
<一个InvalidOperationException从枚举在这一点上抛出>
如果第一次Any
一个测试“如果有的话甚至”走在整个枚举调用,那么该程序将终止而不显示任何消息。 第二个电话放在适当的位置,以表明“如果有任何奇怪的”测试散步导致抛出异常的完整列表。