Checking For Empty Enumerations

code 0 comments suggest edit

While spelunking in some code recently I saw a method that looked something like this:

public void Foo<T>(IEnumerable<T> items) {
  if(items == null || items.Count() == 0) {
    // Warn about emptiness
  }
}

This method accepts a generic enumeration and then proceeds to check if the enumeration is null or empty. Do you see the potential problem with this code? I’ll give you a hint, it’s this line:

items.Count() == 0

What’s the problem? Well that line right there has the potential to be vastly inefficient.

If the caller of the Foo method passes in an enumeration that doesn’t implement ICollection<T> (for example, an IQueryable as a result from an Entity Framework or Linq to SQL query) then the Count method has to iterate over the entire enumeration just to evaluate this expression.

In cases where the enumeration that’s passed in to this method does implement ICollection<T>, this code is fine. The Count method has an optimization in this case where it will simply check the Count property of the collection.

If we translated this code to English, it’s asking the question “Is the count of this enumeration equal to zero?”. But that’s not really the question we’re interested in. What we really want to know is the answer to the question “Are there any elements in this enumeration?

When you think of it that way, the solution here becomes obvious. Use the Any extension method from the System.Linq namespace!

public void Foo<T>(IEnumerable<T> items) {
  if(items == null || !items.Any()) {
    // Warn about emptiness
  }
}

The beauty of this method is that it only needs to call MoveNext on the IEnumerable interface once! You could have an infinitely large enumeration, but Any will return a result immediately.

Even better, since this pattern comes up all the time, consider writing your own simple extension method.

public static bool IsNullOrEmpty<T>(this IEnumerable<T> items) {
    return items == null || !items.Any();
}

Now, with this extension method, our original method becomes even simpler.

public void Foo<T>(IEnumerable<T> items) {
  if(items.IsNullOrEmpty()) {
    // Warn about emptiness
  }
}

With this extension method in your toolbelt, you’ll never inefficiently check an enumeration for emptiness again.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

45 responses

  1. Avatar for Magnus M&#229;rtensson
    Magnus M&#229;rtensson June 9th, 2010

    Thanks man - hadn't really thought about that one!

  2. Avatar for Damian Powell
    Damian Powell June 9th, 2010

    Shouldn't the simpler version be:

    public void Foo<T>(IEnumerable<T> items) {
    if( ! items.IsNullOrEmpty()) {
    // Do something
    }
    }

  3. Avatar for haacked
    haacked June 9th, 2010

    @Damian actually, it was my original sample that was incorrect. I should be checking for null. I just now fixed it. Thanks!

  4. Avatar for Michael Stum
    Michael Stum June 9th, 2010

    Any should definitely be a must-know for every .net Developer, but there is one caveat to add: Iterating over a "volatile" collection (A collection that can only ever move forward, never backward, for example an IEnumerable on top of a network stream) means that you "lose" the first element after the call to any. Arguably, those cases are really rare and devs who are working with it will likely know about it, but it might be helpful to keep in mind.
    Unless I'm completely wrong of course, in which case it's even more important to point out :)

  5. Avatar for NC
    NC June 9th, 2010

    This is completely wrong. The answer was posted on the daily wtf.
    public bool IsListconntSmalleThaOne(IList<IContact> listOfResults) {
    if (listOfResults.Count >= 1)
    {
    return false;
    }
    else
    {
    return true;
    }
    }
    thedailywtf.com/.../IsListconntSmalleThaOne.aspx

  6. Avatar for Priyang
    Priyang June 9th, 2010

    Thanks... Nice one ...

  7. Avatar for tobi
    tobi June 9th, 2010

    I just checked that Any will always create an enumerator. It does not use ICollection. That might be worth improving.

  8. Avatar for Colin Wiseman
    Colin Wiseman June 9th, 2010

    Nice! You see, it's the small bits of code that make things just that wee bit nicer!!

  9. Avatar for Felipe Fujiy
    Felipe Fujiy June 9th, 2010

    And about EF4? Still load all items

  10. Avatar for Michael Meadows
    Michael Meadows June 9th, 2010

    You might consider flipping the extension method. Instead of IsNullOrEmpty, use HasValues. This creates less double negatives in your code.

  11. Avatar for David S.
    David S. June 9th, 2010

    Very cool. It's amazing how the simplest of things can be overlooked.

  12. Avatar for Raj Kaimal
    Raj Kaimal June 9th, 2010

    How about (untested, rough)
    public void Foo<T>(IEnumerable<T> items) {
    if(items == null) {
    // Warn about emptiness
    }
    if (items is ICollection) {
    //check ((ICollection).items).Count == 0
    }
    else {
    //check if items.GetEnumerator().MoveNext() == false
    //call items.GetEnumerator().Reset()
    }
    }
    Maybe the check should be a seperate method.

  13. Avatar for Bryan Watts
    Bryan Watts June 9th, 2010

    If the sequence is a LINQ to SQL or EF query, it will still be executed against the database. All results will be calculated and sent back, but only the first will be materialized to do the Any check. The query will be executed again when the sequence is used. In addition, sequences representing stored procedures may only be enumerated once.

  14. Avatar for tj
    tj June 9th, 2010

    Unfortunately, your IsNullOrEmpty extension method is useless if the item is null. You'll get a null reference excption before it even makes it to the method.

  15. Avatar for Carl H&#246;rberg
    Carl H&#246;rberg June 9th, 2010

    In Linq to SQL:
    .Any(): select case when exists (select null [your query]) then 1 else 0
    .Count(): select count(*) where [your query]

  16. Avatar for Felipe Fujiy
    Felipe Fujiy June 9th, 2010

    Carl Hörberg, I think not in this case.
    Because parameter is IEnumerable<T>, will LazyLoad all table and execute Any() at this collection(in memory)

  17. Avatar for Jason
    Jason June 9th, 2010

    Phil,
    As I posted on Ayende's blog, I'm not liking the semantics of the extension method.
    Calling a method in an instance fashion to check for null should throw a null pointer exception if it's null.
    We don't say "somestring".IsNullOrEmpty, we use String.IsNullOrEmpty(someString)
    Seems counter-intuitive.
    TJ:
    No, it will work just fine. The compiler changes it to a static call which accepts null arguments just fine like any other method.
    That's the problem though. Looking at it, it should throw an NPE, but it doesn't.

  18. Avatar for chublogga
    chublogga June 9th, 2010

    I came up with some other extension methods to circumvent having to count the entire enumeration when comparing numbers:

    public static bool CountGreaterThanOrEqualTo<T> (this IEnumerable<T> items, int numItems)
    {
    if (numItems < 0) throw new ArgumentOutOfRangeException ("numItems must be >= 0");
    if (numItems == 0) return true;
    int count = 0;
    foreach (var item in items)
    {
    count++;
    if (count >= numItems) return true;
    }
    return false;
    }

  19. Avatar for Troels Thomsen
    Troels Thomsen June 9th, 2010

    I really believe you shouldn't set up null-guards across your entire code base. Ensure that you don't call your methods with nulls instead... It's both simpler and prettier; null is a special value with a distinct semantic purpose, which entirely gets lost if we interpret a null value and an empty sequence as the same thing.

  20. Avatar for Seth Petry-Johnson
    Seth Petry-Johnson June 9th, 2010

    I use the very same .IsNullOrEmpty() extension all the time, and I also have defined its inverse .IsNotNullOrEmpty(). I like using this for strings as well as sequences because it provides a very consistent way of writing null handling code.
    @Troels: I have to disagree a little bit. Helpers like ".IsNotNullOrEmpty()" are very useful in presentation code when we only want to output data if there is non-null, non-empty data to display.
    In general I prefer the defensive programming approach of "if you can deal with nulls gracefully, do so". A decent library of extensions goes a long way to keeping the code clean and elegant and helps avoid regression issues when code changes and you suddenly start receiving null arguments. (Of course, if you _can't_ deal gracefully with nulls then you should throw an explicit exception, but many times a null or empty check is fine)

  21. Avatar for George Tsiokos
    George Tsiokos June 10th, 2010

    public static bool IsNullOrEmpty (this ICollection items) {
        if (null == items)
            return true;
        return items.Count > 0;
    }
    public static bool IsNullOrEmpty (this IEnumerable items) {
        if (null == items)
            return true;
        ICollection collection = items as ICollection;
        if (null != collection)
            return collection.Count > 0;
        return !items.Cast<object> ().Any ();
    }

  22. Avatar for chrido
    chrido June 10th, 2010

    People just don't get the difference between Enumerators and Lists and which different access guarantees they have. Having the need for that kind of null-check code is a design smell.
    Have a look at the following sample to get an idea why Enumerators are just not Lists and all the codes shown here do not work:
    namespace ConsoleApplication1
    {
    class Program
    {
    static void Main(string[] args)
    {
    IEnumberalbe<object> someObject = GetSomeObjects();

    if(!IsNullOrEmpty(someObject))
    {
    foreach (var o in someObject)
    {
    //bamm
    }
    }
    }
    public static bool IsNullOrEmpty<T>(IEnumerable<T> items)
    {
    return items == null || !items.Any();
    }
    private static bool accessed = false;
    public static IEnumerable<object> GetSomeObjects()
    {
    if(accessed == false)
    {
    accessed = true;
    yield return new object();
    }
    else
    {
    throw new NullReferenceException();
    }
    }
    }
    }

  23. Avatar for James Hare
    James Hare June 10th, 2010

    Personally, I like declaring both an IEnumerable IsNullOrEmpty and an ICollection IsNullOrEmpty. With ICollection IsNullOrEmpty, you can take advantage of the Count PROPERTY which is const time and doesn't create an Enumerator. And then I also like creating the IsNotNullOrEmpty as well...
    public static bool IsNullOrEmpty<T>(this ICollection<T> input)
    {
    return (input == null) || (input.Count == 0);
    }
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
    return (source == null) || (!source.Any());
    }

  24. Avatar for Luis Abreu
    Luis Abreu June 10th, 2010

    hum...I'm not sure I believe I'm seeing this code...
    When I started looking at extension methods, there was a recommendation saying that extension methods should behave like instance methods. This code simply doesn't do that! Lets say I have a variable x of type X. x.Method() should only be allowed if x is not null. In all the other cases it should through a null reference exception. That's how it should be and that's why extension methods should do the same thing. that's why in (in my opinion) this method should be a simple static method and not an extension method...

  25. Avatar for James Hare
    James Hare June 10th, 2010

    I used to feel strongly that way as well, but I feel that the semantics of the name (IsNullOrEmpty) justify an exceptionin this case. The point of the extension method is to make it easier to check for null or empty, which i think it does in a very elegant fashion.
    Would it be more correct as a static method? Sure, and you can still call it that way if you wish or code it that way, but in many cases where we are trying to make libraries that are easier and more fluent, I'd argue for ease of use more than semantics.
    With the extension method you get the benefit of Intellisense telling you it's available for use immediately, whereas as simply a static method, you'd have to know the name of the class and that it exists (no intellisense help from your target instance).
    So is a static method more pure? Absolutely! But I think in this case where the intention is clear that you are checking the reference for null (or empty) it is justified.
    But that's just my $0.02 :-)

  26. Avatar for Paulo Morgado
    Paulo Morgado June 13th, 2010

    I'll second Luís.
    At any time, the designer of the extended type can include that method in the type which would make code exetending on null references to throw a NullReferenceException.
    A very bad practice in deed.

  27. Avatar for Tom Anderson
    Tom Anderson June 13th, 2010

    Something here looks a bit smell.
    If you are dealing with IEnumerable and it is not null, then the Enumerator will take care of the logic (MoveNext returning false) if the underlying data is empty.
    I don't think you should be levying your code at this level. If you are expecting results to not be empty, it sounds like something of an API issue where you require values back in a collection, which to me, should always be handled as "the IEnumerable could be empty".

  28. Avatar for James Michael Hare
    James Michael Hare June 13th, 2010

    @Tom: True, there are may times that a check for an empty enumeration can be avoided (for instance a check for size zero around a foreach is unnecessary), but there may also be validation logic where you may expect an enumeration to have at least one element and zero elements is an error.

  29. Avatar for James Michael Hare
    James Michael Hare June 13th, 2010

    @Paulo: An interesting point although you'd think if the designer were coding an extension method for a class under their control they would have just modified the original class.
    Like I said, 99% of the time, I agree that an extension behaving safely on a null creates some interesting design issues. It is curious, though, that with MS recommending that extension methods should behave like real methods that they didn't put an implicit NullReferenceException if the target "this" instance was null.
    It's like they allow for it syntactically but then say you shouldn't quite do it. Kinda mixed signals.

  30. Avatar for Dilyan Rusev
    Dilyan Rusev June 13th, 2010

    I think this code is not better than Count(), because both of them execute the IQueryable (call Execute, or, rather, GetEnumerable). If we deal with collections (which is almost always the case with Linq-To-Objects in my experience), Count() might even peform better (especially for arrays and IList-s), because it won't have to create an additional object and initialzie it (the enumerator).

  31. Avatar for Troels Thomsen
    Troels Thomsen June 13th, 2010

    @Seth Petry-Johnson: I don't like code for presentation. I'd prefer a templating language that abstracts these things away. I also can't see why you'd send a null collection to some presentation code. You can fix that issue at the source and always assign the collection instead.
    Null guards will quickly polute your code base. By accepting it a single place, you'll have to deal with it everywhere. You don't start receiving null arguments unless you at some point accepted it in the first place. Fail fast.

  32. Avatar for Marcel Popescu
    Marcel Popescu June 13th, 2010

    @Troels - I agree with you in theory, but I still haven't been able to apply this to my situation: I write WCF services which can receive very complex objects (very wide AND deep - up to maybe 15 levels deep, if not worse). These objects can describe people, businesses, addresses, contact information... a lot of stuff. So... I find it easier to call a method with M(PersonInfo) and let that method check for possible nulls in the properties of the PersonInfo object rather than move the checks before the call to M()... call that can occur multiple times.
    I would indeed prefer to only check the input once - I am regularly bitten by null reference exceptions - but I fear that it would complicate the code too much and create more problems than it solves.

  33. Avatar for Conor
    Conor June 13th, 2010

    I don't think Any() will always return immediately. What if the argument is the result of a Where() call? If it results in an empty list, it will have to iterate all infinite elements...no?

  34. Avatar for James Hare
    James Hare June 13th, 2010

    @Conor: Not sure I understand what you're saying. If the where clause reduces it to an empty set, then the MoveNext() in Any() returns false a Any() returns false. Unless you're thinking of something specific?
    Otherwise here's what I see in Reflector for Any():

    public static bool Any<TSource>(this IEnumerable<TSource> source)
    {
    if (source == null)
    {
    throw Error.ArgumentNull("source");
    }
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
    if (enumerator.MoveNext())
    {
    return true;
    }
    }
    return false;
    }

  35. Avatar for Conor
    Conor June 13th, 2010

    Yeah that's right, I'm just saying that to actually do MoveNext(), won't it will have to evaluate the Where() clause for each element until it finds one that matches? If I have a list of all the positive integers and I pass to Foo posInts.Where(x => x < 0) for example..

  36. Avatar for James Hare
    James Hare June 13th, 2010

    Makes sense. Thanks for the clarification.

  37. Avatar for Jimbo
    Jimbo June 14th, 2010

    Seth,
    Don't you mean .IsNotNullNorEmpty()?
    Four negatives in an extension method makes me antsy.

  38. Avatar for Dan Atkinson
    Dan Atkinson June 14th, 2010

    I also wrote an extension where you can pass a query and check whether that's returned with any results.

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source, Func<T, bool> query)
    {
    return source == null || !source.Any(query);
    }

  39. Avatar for Tuomas Hietanen
    Tuomas Hietanen June 15th, 2010

    Hi!
    Better solution than use null or zero count, is to use "Special Case" -pattern (Fowler PoEAA). In C# there is already a Microsoft .NET Framework implementation of it: Enumerable.Empty.
    var myEmptyList = Enumerable.Empty<T>();
    In F# you can use the option type.

  40. Avatar for Vaduganathan
    Vaduganathan June 16th, 2010

    Any way thank you very much.
    Now I am clear that where I can use method and property and how it swallow execution time.

  41. Avatar for Martin R-L
    Martin R-L June 16th, 2010


    An exception to go with that?
    /// &lt;summary&gt;
    /// Throw when the pre-condition stipulates that a sequence param, e.g. a string or
    /// enumerable, mustn't be null nor empty (e.g. Length == 0, Count/Count() == 0,
    /// or Any() == false).
    /// &lt;/summary&gt;
    public class ArgumentNullOrEmptyException : ArgumentNullException
    {
    public ArgumentNullOrEmptyException(string paramName) : base(paramName)
    {}
    public override string Message
    {
    get
    {
    return "Value cannot be null nor empty.{0}Parameter name: {1}".FormatWith(Environment.NewLine, ParamName);
    }
    }
    }
    ... where FormatWith is a simple extension method wrapping String.Format defaulting to use the invariant culture.

  42. Avatar for Martin R-L
    Martin R-L June 17th, 2010

    Oh, so the blog does html encoding?
    /// <summary>
    /// Throw when the pre-condition stipulates that a sequence, e.g. a string or
    /// enumerable, mustn't be null nor empty (e.g. Length == 0, Count/Count() == 0,
    /// or Any() == false).
    /// </summary>
    public class ArgumentNullOrEmptyException : ArgumentNullException
    {
    public ArgumentNullOrEmptyException( string paramName ) : base( paramName )
    {}
    public ArgumentNullOrEmptyException( string paramName, string message ) : base( paramName, message )
    {}
    public override string Message
    {
    get
    {
    return "Value cannot be null nor empty.{0}Parameter name: {1}".FormatWith( Environment.NewLine, ParamName );
    }
    }
    }

  43. Avatar for Jay
    Jay September 4th, 2011

    Resurrecting an old discussion, I'll throw in another, doubtlessly controversial contender:
    if (items == Null.OrEmpty)…
    or
    if ("foo bar" != Null.OrEmpty)…
    codequota.com/...

  44. Avatar for sarah
    sarah March 8th, 2015

    very good advice.

    i hadn't thought about going so far as to mock out the internet using Hosts file. That's a great idea, as conference wifi is always patchy.

  45. Avatar for Kevin Hollingshead
    Kevin Hollingshead January 4th, 2016

    Did not know about the ".Any()" method until today. Note that you can use the overload that takes a lambda to ask "Are there any people named Mike?", e.g. "if (people.Any(x => x.first_name == "Mike")). Thanks for, uh, Haacking me? :)