IEnumerable count without enumeration

How to (possibility) get an IEnumerable count with TryGetNonEnumeratedCount

Home DailyDrop

Daily Knowledge Drop

The TryGetNonEnumeratedCount method (introduced in .NET6) can be used to attempt to determine the number of elements in a sequence without forcing an enumeration over the sequence.

Some implementations of IEnumerable<> can have the count determined without enumerating over all the items, while other implementations require an enumeration. TryGetNonEnumeratedCount will perform a series of type tests, identifying common types whose count can be determined without enumerating.


Example

Consider the following sample - first, a method which will return an IEnumerable<string> of shipping options:

public IEnumerable<string> GetShippingOptions()
{
    yield return "Pickup";
    yield return "Express";
    yield return "Overnight";
    yield return "Standard";
    yield return "Overseas shipping";
}

Next, we have a method which accepts an IEnumerable<string> implementation, and will:

  • Try to get the count without enumerating using the TryGetNonEnumeratedCount method
  • If unable to get the count without enumerating, then enumerate the sequence using the Count method
  • Return the count of items in the sequence
public int GetCount(IEnumerable<string> options)
{
    if (options.TryGetNonEnumeratedCount(out var count))
    {
        Console.WriteLine($"TryGetNonEnumeratedCount success! Count => {count}");
        return count;
    }
    else
    {
        var enumerateCount = options.Count();
        Console.WriteLine($"TryGetNonEnumeratedCount fail! " +
            $"Have to enumerate. Count => {enumerateCount}");
        return enumerateCount;
    }
}

Lastly, lets call the GetCount method with different implementations of IEnumerable<string>:

// options is IEnumerable<string> as per 
// GetShippingOptions return type
var options = GetShippingOptions();

var ienumerableCount = GetCount(options);
var listCount = GetCount(options.ToList());
var arrayCount = GetCount(options.ToArray());

Executing this, the output is:

TryGetNonEnumeratedCount fail! Have to enumerate. Count => 5
TryGetNonEnumeratedCount success! Count => 5
TryGetNonEnumeratedCount success! Count => 5

Notes

When working with IEnumerable, and various implementations, it might be advantageous (with regards to performance) to first check if the count can be retrieved without enumerating, using the TryGetNonEnumeratedCount method, and only if that's not possible then using a method (such as Count) which enumerates over the sequence.

As always, benchmark your specific use case and expected IEnumerable size, to determine which method makes sense and results in better performance.


References

Avoiding enumeration with 'TryGetNonEnumeratedCount'

Daily Drop 82: 26-05-2022

At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.

The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.
c# .net ienumerable enumeration count