Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 240
Chris Ammerman Avatar asked Sep 22 '08 20:09

Chris Ammerman


3 Answers

!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.

like image 84
Guvante Avatar answered Nov 03 '22 12:11

Guvante


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();
}
like image 31
Matt Avatar answered Nov 03 '22 12:11

Matt


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.

like image 35
Joe Avatar answered Nov 03 '22 14:11

Joe