Checking For Empty Enumerations

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.

What others have said

Requesting Gravatar... Magnus Mårtensson Jun 09, 2010 4:37 PM
# re: Checking For Empty Enumerations
Thanks man - hadn't really thought about that one!
Requesting Gravatar... Damian Powell Jun 09, 2010 4:39 PM
# re: Checking For Empty Enumerations
Shouldn't the simpler version be:


public void Foo<T>(IEnumerable<T> items) {
if( ! items.IsNullOrEmpty()) {
// Do something
}
}
Requesting Gravatar... haacked Jun 09, 2010 4:42 PM
# re: Checking For Empty Enumerations
@Damian actually, it was my original sample that was incorrect. I should be checking for null. I just now fixed it. Thanks!
Requesting Gravatar... Michael Stum Jun 09, 2010 4:57 PM
# re: Checking For Empty Enumerations
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 :)
Requesting Gravatar... NC Jun 09, 2010 5:08 PM
# re: Checking For Empty Enumerations
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
Requesting Gravatar... Priyang Jun 09, 2010 5:25 PM
# re: Checking For Empty Enumerations
Thanks... Nice one ...
Requesting Gravatar... tobi Jun 09, 2010 6:18 PM
# re: Checking For Empty Enumerations
I just checked that Any will always create an enumerator. It does not use ICollection. That might be worth improving.
Requesting Gravatar... Colin Wiseman Jun 09, 2010 6:26 PM
# re: Checking For Empty Enumerations
Nice! You see, it's the small bits of code that make things just that wee bit nicer!!
Requesting Gravatar... Felipe Fujiy Jun 09, 2010 8:07 PM
# re: Checking For Empty Enumerations
And about EF4? Still load all items
Requesting Gravatar... Michael Meadows Jun 09, 2010 8:11 PM
# re: Checking For Empty Enumerations
You might consider flipping the extension method. Instead of IsNullOrEmpty, use HasValues. This creates less double negatives in your code.
Requesting Gravatar... David S. Jun 09, 2010 10:15 PM
# re: Checking For Empty Enumerations
Very cool. It's amazing how the simplest of things can be overlooked.
Requesting Gravatar... Raj Kaimal Jun 09, 2010 10:34 PM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... Bryan Watts Jun 09, 2010 10:41 PM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... tj Jun 09, 2010 11:10 PM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... Carl Hörberg Jun 09, 2010 11:11 PM
# re: Checking For Empty Enumerations
In Linq to SQL:

.Any(): select case when exists (select null [your query]) then 1 else 0

.Count(): select count(*) where [your query]
Requesting Gravatar... Felipe Fujiy Jun 09, 2010 11:30 PM
# re: Checking For Empty Enumerations
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)
Requesting Gravatar... Jason Jun 09, 2010 11:32 PM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... chublogga Jun 10, 2010 12:02 AM
# re: Checking For Empty Enumerations
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;
}
Requesting Gravatar... Troels Thomsen Jun 10, 2010 1:27 AM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... Seth Petry-Johnson Jun 10, 2010 2:53 AM
# re: Checking For Empty Enumerations
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)
Requesting Gravatar... George Tsiokos Jun 10, 2010 3:35 AM
# re: Checking For Empty Enumerations
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 ();
}
Requesting Gravatar... chrido Jun 10, 2010 5:09 AM
# Enumerator != List
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();
}
}
}
}
Requesting Gravatar... James Hare Jun 10, 2010 11:08 PM
# re: Checking For Empty Enumerations
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());
}
Requesting Gravatar... Luis Abreu Jun 10, 2010 11:29 PM
# re: Checking For Empty Enumerations
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...
Requesting Gravatar... James Hare Jun 10, 2010 11:49 PM
# re: Checking For Empty Enumerations
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 :-)
Requesting Gravatar... Paulo Morgado Jun 13, 2010 8:44 AM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... Tom Anderson Jun 13, 2010 9:06 AM
# re: Checking For Empty Enumerations
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".
Requesting Gravatar... James Michael Hare Jun 13, 2010 9:15 AM
# re: Checking For Empty Enumerations
@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.
Requesting Gravatar... James Michael Hare Jun 13, 2010 9:44 AM
# re: Checking For Empty Enumerations
@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.
Requesting Gravatar... Dilyan Rusev Jun 13, 2010 4:03 PM
# re: Checking For Empty Enumerations
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).
Requesting Gravatar... Troels Thomsen Jun 13, 2010 5:00 PM
# re: Checking For Empty Enumerations
@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.
Requesting Gravatar... Marcel Popescu Jun 13, 2010 7:07 PM
# re: Checking For Empty Enumerations
@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.
Requesting Gravatar... Conor Jun 13, 2010 11:14 PM
# re: Checking For Empty Enumerations
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?
Requesting Gravatar... James Hare Jun 14, 2010 12:01 AM
# re: Checking For Empty Enumerations
@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;
}
Requesting Gravatar... Conor Jun 14, 2010 12:10 AM
# re: Checking For Empty Enumerations
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..
Requesting Gravatar... James Hare Jun 14, 2010 12:56 AM
# re: Checking For Empty Enumerations
Makes sense. Thanks for the clarification.
Requesting Gravatar... Jimbo Jun 14, 2010 10:04 AM
# re: Checking For Empty Enumerations
Seth,

Don't you mean .IsNotNullNorEmpty()?

Four negatives in an extension method makes me antsy.
Requesting Gravatar... Dan Atkinson Jun 14, 2010 10:59 PM
# re: Checking For Empty Enumerations
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);
}
Requesting Gravatar... Tuomas Hietanen Jun 15, 2010 8:58 PM
# re: Checking For Empty Enumerations
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.
Requesting Gravatar... Vaduganathan Jun 16, 2010 3:11 PM
# re: Checking For Empty Enumerations
Any way thank you very much.

Now I am clear that where I can use method and property and how it swallow execution time.
Requesting Gravatar... Martin R-L Jun 16, 2010 6:13 PM
# re: Checking For Empty Enumerations

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.
Requesting Gravatar... Martin R-L Jun 17, 2010 3:26 PM
# re: Checking For Empty Enumerations
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 );
}
}
}
Requesting Gravatar... Jay Sep 04, 2011 11:33 AM
# re: Checking For Empty Enumerations
Resurrecting an old discussion, I'll throw in another, doubtlessly controversial contender:

if (items == Null.OrEmpty)…

or

if ("foo bar" != Null.OrEmpty)…

codequota.com/...

What do you have to say?

(will show your gravatar)
Please add 1 and 7 and type the answer here: