views:

542

answers:

4

A method returns a sequence, IEnumerable<T>, and you now want to check if it is empty. How do you recommend doing that? I'm looking for both good readability and good performance.

The first and most obvious way is to check that the count is greater than zero:

if(sequence.Count() == 0)

Has decent readability, but terrible performance since it has to actually go through the whole sequence.

A method that I sometimes use is the following:

if(!sequence.Any())

This doesn't (as far as I know) have to go through the whole sequence, but the readability is a bit backwards and awkward. (Reads a lot better if we are checking that the sequence is not empty though).

Another option is to use First in a try-catch, like this:

try
{
    sequence.First();
}
catch(InvalidOperationException)
{
    // Do something
}

Not a very pretty solution, and probably slower too, since it is using exceptions and stuff. Could prevent that by using FirstOrDefault of course, except you would have a big problem if the first item in the sequence actually was the default value ;)

So, any other ways to check if a sequence is empty? Which one do you usually use? Which one do you recommend to use?

Note: For optimal readability I would probably put one of the above snippets in an IsEmpty extension method, but I am still curious since I would have to do something inside that method as well :p

+2  A: 

Well all these methods you're calling are LINQ extension methods, so it depends how the LINQ provider was implemented. If you want to know if a sequence is empty, either Count() == 0 or Any() == false is appropriate. I prefer Any() myself.

However, depending on what actual Type your sequence is, you might not need to use a LINQ extension method. I.e. if it's an array you can call sequence.Length. If it's a collection, you can use sequence.Count.

Neil Barnwell
+23  A: 

I would use !sequence.Any(), personally.

If you really need to, you could always write your own extension method:

public static void IsEmpty<T>(this IEnumerable<T> source)
{
    return !source.Any();
}

Then you can write:

if (sequence.IsEmpty())
Jon Skeet
+1, I created an extension method in my own app because it's easier to read "if empty" then "if not any".
Meta-Knight
+1, looking into reflector shows `sequence.Any()` as being the clear winner. Is there any reason you wouldn't want to add this extension ?..I was just wondering what the italic on "really" in emphasizing.
Dynami Le Savard
A: 

You can create an Extension method, with this implementation.

public static bool IsEmpty<T>(this IEnumerable<T> items) {
            var enumerator = items.GetEnumerator();
            return !enumerator.MoveNext();
        }
Amby
Hm, I suppose that is maybe what the Any method really does under the covers?
Svish
A: 

You said:

if(sequence.Count() == 0) Has decent readability, but terrible performance since it has to actually go through the whole sequence.

Is that actually true? You are talking about dealing with an Interface, IEnumerable<T>, and yet you are making assumptions regarding its implementation which may or may not be true. In fact, many of the custom collections I've written over the years keep a private variable that stores the current count internally, which means that returning .Count is a trivial matter that does not require iterating the entire collection.

So with that said, unless you know that a specific implementation is poorly optimized for .Count, I would use .Count. Avoid premature optimization wherever possible, and stick with readability.

Nick
As you say - you're dealing with an interface which does not specify how the count is calculated, so you have to assume that it could be an O(n) operation. How is it premature optimisation to use `Any` instead of `Count`? Using a method which is **designed exactly for this purpose** and **guarantees O(1) time** is not premature optimisation, it's simply not being lax.
Greg Beech
Hm, yeah, exactly. Since I in general have no idea what kind of collection it is, I prefer to be on the safe side. As long as the safe side is not an extremely complicated one. And in this case it isn't. If you do however know that it is a list or an array for instance, I would agree that using the `Count` or `Length` can be a good option. Although I might still choose to stick to the `IsEmpty` extension method for consistency :)
Svish
Count will check to see if the sequence it's working with is really an array, and if so will return Length. Likewise, it will check for ICollection, and return Count. But the sequence could just as easily be an infinite sequence generated by an iterator expression, in which case you're going to wait an awfully long time just to find out whether the sequence is empty or not. Any() is far more reliable when you don't know the underlying sequence type.
Joel Mueller
And if you're using .NET 2.0? I kind of enjoy reminding people of these little "old fashioned" artifacts from earlier versions of the framework b/c sometimes people forget that not everybody has the ability to use the latest and greatest.
Nick