48

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

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Svish
  • 152,914
  • 173
  • 462
  • 620

6 Answers6

82

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

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

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

Then you can write:

if (sequence.IsEmpty())
Doug Clutter
  • 3,646
  • 2
  • 29
  • 31
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    +1, I created an extension method in my own app because it's easier to read "if empty" then "if not any". – Meta-Knight Jan 19 '10 at 15:52
  • 6
    +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 Jan 19 '10 at 18:38
  • 2
    A nice IEnumerable IsNullOrEmpty() extension method is here: http://haacked.com/archive/2010/06/10/checking-for-empty-enumerations.aspx – Tim Lewis Jun 15 '12 at 15:05
  • 3
    @Dynami Le Savard: if the content of IEnumerable is not yet computed (eg you're using Linq), a problem is that you may not realize that you execute things twice: calling IsEmpty will execute your Linq query, and then if it's not empty you may do a foreach and again reexecute your query. – user276648 Jun 21 '12 at 03:53
  • @TimLewis probably because it wouldn't really add any value at all, it'd just make the API larger and thus harder to grasp. you'de see SO-questions asking about the performace differences between Any and IsEmpty and discussions about which is more readable and so on. if you personally feel that Any (or !Any which literally reads as "not any" which is pretty easy to understand for me) is too hard to understand, you can roll your own wrapper method. – sara Apr 02 '16 at 13:08
  • I think `Empty` or `None` reads better in the spirit of LINQ. The verb `Is` doesnt sound functional enough :) – nawfal May 21 '20 at 09:09
  • @nawfal: I disagree - both `Empty` and `None` sound like methods that *produce* empty sequences. Like the existing `Enumerable.Empty` method, for example. – Jon Skeet May 21 '20 at 09:17
  • @jon makes sense. I never liked the naming Single, which implies if count ==1 to me, though it is about getting a single item in it. – nawfal May 21 '20 at 09:32
6

You can create an Extension method, with this implementation.

public static bool IsEmpty<T>(this IEnumerable<T> items) {
        using (var enumerator = items.GetEnumerator())
        {
            return !enumerator.MoveNext();
        }
 }
Manish Basantani
  • 16,931
  • 22
  • 71
  • 103
2

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
  • 41,080
  • 29
  • 148
  • 220
  • I don't feel it is good advice to recommend `Count() == 0` vs `Any() == false` as being on equal footing, given that it is known that for some `IEnumerables` `Count` is much more expensive. Surely `Any` is the safer, and therefore superior, choice? – ToolmakerSteve Nov 27 '18 at 07:23
  • I prefer `Any()`, although in practice I'm pretty sure some types still have to do a count internally to return that result. Besides, `Any()` describes the intent of the code better, which I why I recommend it over `Count()`. – Neil Barnwell Nov 30 '18 at 15:17
1

I use this extension methods to detect if the sequence is null or does not have any item and alternatively to detect if the sequence does have at least one item, much like the string.IsNullOrEmpty() method.

 public static bool IsNullOrEmpty<TSource>(this IEnumerable<TSource> source) {
     if (source == null) {
        return true;
     }

     return !source.Any();
 }

 public static bool IsNotNullOrEmpty<TSource>(this IEnumerable<TSource> source) {
     return !source.IsNullOrEmpty();
 }
 .
 .
 .
 if (!sequence.IsNullOrEmpty()) {
     //Do Something with the sequence...
 }
Sagi
  • 8,972
  • 3
  • 33
  • 41
  • FWIW, for the second method, I suggest the name "HasItems" - shorter and more readable than the double-negative "IsNotNullOrEmpty". – ToolmakerSteve Nov 27 '18 at 07:16
  • Oops. I downvoted this when I saw you calling a method on a value that might be null, but that was my mistake, given that this is an *extension* method, so is still invoked as a static method, despite the "." syntax. Sorry, too late for me to remove my downvote unless the answer is edited. I don't understand why SO doesn't allow removal of downvotes in this case. :( – ToolmakerSteve Nov 27 '18 at 07:33
0

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
  • 5,875
  • 1
  • 27
  • 38
  • 5
    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 Jan 19 '10 at 18:28
  • 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 Jan 19 '10 at 18:53
  • 2
    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 Jan 19 '10 at 19:00
  • 1
    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 Jan 19 '10 at 21:44
  • 2
    For the sake of future readers, I will point out that the extension method IEnumerable.Count will check to see if the source is also an ICollection or ICollection. If it is, then Count will be called on this interface. Otherwise the extension method does enumerate the entire collection to count items. – Richard Robertson Jan 05 '15 at 16:37
0

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

  1. According to Microsoft, Any does indeed not have to go through the whole sequence. Quoting from the section Remarks:

The enumeration of source is stopped as soon as the result can be determined.

  1. This is particularly true when testing for the presence of elements in an if-else statement. Arguably, readability is best if one tests for the presence of elements in the if statement, and the absence of elements in the else, thereby avoiding the use of the ! operator:

    if (sequence.Any())
    {
    }
    else
    {
    }
    

    Most would consider that more readable than:

    if (!sequence.Any())
    {
    }
    else
    {
    }
    
DavidRR
  • 18,291
  • 25
  • 109
  • 191