What is a solid, elegant, reusable piece of code for determining if an IEnumerable is empty, in .NET?

StackOverflow https://stackoverflow.com/questions/117355

  •  02-07-2019
  •  | 
  •  

Question

I'm trying to find the most reusable, yet elegant, piece of code possible for determining if an IEnumerable. In the ideal, this should be a function I can call absolutely any time I need to tell if an IEnumerable is empty.

While I have developed an answer for .NET 3.5 that has worked well for me so far, my current thought is that there is no perfect answer, since an IEnumerable can technically encapsulate a collection (or queue of iterators) that modifies the underlying results as it iterates, which would cause problems. However, this would also be an impediment to implementing IEnumerable.Count(), and that didn't stop MS from providing it.

So I thought I'd put it to SO to see if someone has a better one, and in case someone else should find it useful.

Edit: Wow, I can't believe I didn't know about IEnumerable.Any. I knew it existed, but never bothered to check what it did. Let this be a lesson. Read the documentation. Just because a method name doesn't imply it does what you want, doesn't mean it doesn't do what you want.

Was it helpful?

Solution

!enumerable.Any()

Will attempt to grab the first element only.

To expand on how/why this works, any determines if any of the components of an IEnumerable match a given function, if none is given, then any component will succeed, meaning the function will return true if an element exists in the enumerable.

OTHER TIPS

For .net 1/2:

IEnumerator e;
try
{
   e = enumerable.GetEnumerator();
   return e.MoveNext();
}
finally
{ 
    if (e is IDisposable)
        e.Dispose();
}

Or, with generics:

using (IEnumerator<T> e = enumerable.GetEnumerator())
{
    return e.MoveNext();
}

You're right that there is no perfect answer. IEnumerable only supports iteration and doesn't guarantee that the enumeration is repeatable. You can't find out if an enumeration contains elements without calling MoveNext at least once, and once you've done so you can't guarantee to be able to reuse the enumeration: it is allowable for IEnumerable.Reset to throw a NotSupportedException. From http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx:

"The Reset method is provided for COM interoperability. It does not necessarily need to be implemented; instead, the implementer can simply throw a NotSupportedException."

Extension methods like IEnumerable<T>.Count and IEnumerable<T>.Any need to call MoveNext under the covers. Useful wrappers, but don't avoid the fact that in the (rare) cases where an enumeration doesn't support Reset, you could have a problem.

One thing to be careful of with either of these methods is that not all enumerations can be rolled-back, for instance all implementations of System.Data.IDataReader can only run through once.

In these cases you don't really have a cost in a foreach loop, so long as you account for the fact that it might not even loop once.

The first method has a simple implementation of Empty extension method: http://signum.codeplex.com/SourceControl/changeset/view/25903#510468

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top