From 0d74d1d515926055ca4b4871e8002210755a7369 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 4 Mar 2024 10:45:14 -0500 Subject: [PATCH] Use Iterator.TryGetFirst in Enumerable.Any() (#99218) Enumerable.Any() currently uses TryGetNonEnumeratedCount, comparing the result to 0, and TryGetNonEnumeratedCount uses `Iterator.GetCount(onlyIfCheap: true)`. But this leaves out iterators for which it's not cheap to compute the count; for these, however, we can now benefit from every `Iterator` providing a `TryGetFirst`; its `found` result can be used as the result of `Any`. This PR inlines TryGetNonEnumeratedCount into Any and then updates its use of `Iterator` to first use GetCount and then fall back to using TryGetFirst if GetCount is unsuccessful. --- .../System.Linq/src/System/Linq/AnyAll.cs | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/AnyAll.cs b/src/libraries/System.Linq/src/System/Linq/AnyAll.cs index 1fd5e5b4ae447..4fe6ae0b1b9bd 100644 --- a/src/libraries/System.Linq/src/System/Linq/AnyAll.cs +++ b/src/libraries/System.Linq/src/System/Linq/AnyAll.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Generic; namespace System.Linq @@ -9,15 +10,37 @@ public static partial class Enumerable { public static bool Any(this IEnumerable source) { - return - TryGetNonEnumeratedCount(source, out int count) ? count != 0 : - WithEnumerator(source); + if (source is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } - static bool WithEnumerator(IEnumerable source) + if (source is ICollection gc) { - using IEnumerator e = source.GetEnumerator(); - return e.MoveNext(); + return gc.Count != 0; } + +#if !OPTIMIZE_FOR_SIZE + if (source is Iterator iterator) + { + int count = iterator.GetCount(onlyIfCheap: true); + if (count >= 0) + { + return count != 0; + } + + iterator.TryGetFirst(out bool found); + return found; + } +#endif + + if (source is ICollection ngc) + { + return ngc.Count != 0; + } + + using IEnumerator e = source.GetEnumerator(); + return e.MoveNext(); } public static bool Any(this IEnumerable source, Func predicate)