Skip to content

Commit

Permalink
Use Iterator<T>.TryGetFirst in Enumerable.Any() (dotnet#99218)
Browse files Browse the repository at this point in the history
Enumerable.Any() currently uses TryGetNonEnumeratedCount, comparing the result to 0, and TryGetNonEnumeratedCount uses `Iterator<T>.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<T>` 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<T>` to first use GetCount and then fall back to using TryGetFirst if GetCount is unsuccessful.
  • Loading branch information
stephentoub authored Mar 4, 2024
1 parent 061d4df commit 0d74d1d
Showing 1 changed file with 29 additions and 6 deletions.
35 changes: 29 additions & 6 deletions src/libraries/System.Linq/src/System/Linq/AnyAll.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -9,15 +10,37 @@ public static partial class Enumerable
{
public static bool Any<TSource>(this IEnumerable<TSource> source)
{
return
TryGetNonEnumeratedCount(source, out int count) ? count != 0 :
WithEnumerator(source);
if (source is null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}

static bool WithEnumerator(IEnumerable<TSource> source)
if (source is ICollection<TSource> gc)
{
using IEnumerator<TSource> e = source.GetEnumerator();
return e.MoveNext();
return gc.Count != 0;
}

#if !OPTIMIZE_FOR_SIZE
if (source is Iterator<TSource> 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<TSource> e = source.GetEnumerator();
return e.MoveNext();
}

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
Expand Down

0 comments on commit 0d74d1d

Please sign in to comment.