Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if a list is empty with LINQ

Tags:

c#

.net

list

linq

People also ask

How do you check whether a list is empty or not in C#?

Now to check whether a list is empty or not, use the Count property. if (subjects. Count == 0) Console.

How do you check if a list is empty or null?

isEmpty() method of CollectionUtils can be used to check if a list is empty without worrying about null list. So null check is not required to be placed everywhere before checking the size of the list.

How do you check if a list is empty in Python?

In this solution, we use the len() to check if a list is empty, this function returns the length of the argument passed. And given the length of an empty list is 0 it can be used to check if a list is empty in Python.


You could do this:

public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
    if (source == null)
        return true; // or throw an exception
    return !source.Any();
}

Edit: Note that simply using the .Count method will be fast if the underlying source actually has a fast Count property. A valid optimization above would be to detect a few base types and simply use the .Count property of those, instead of the .Any() approach, but then fall back to .Any() if no guarantee can be made.


I would make one small addition to the code you seem to have settled on: check also for ICollection, as this is implemented even by some non-obsolete generic classes as well (i.e., Queue<T> and Stack<T>). I would also use as instead of is as it's more idiomatic and has been shown to be faster.

public static bool IsEmpty<T>(this IEnumerable<T> list)
{
    if (list == null)
    {
        throw new ArgumentNullException("list");
    }

    var genericCollection = list as ICollection<T>;
    if (genericCollection != null)
    {
        return genericCollection.Count == 0;
    }

    var nonGenericCollection = list as ICollection;
    if (nonGenericCollection != null)
    {
        return nonGenericCollection.Count == 0;
    }

    return !list.Any();
}

LINQ itself must be doing some serious optimization around the Count() method somehow.

Does this surprise you? I imagine that for IList implementations, Count simply reads the number of elements directly while Any has to query the IEnumerable.GetEnumerator method, create an instance and call MoveNext at least once.

/EDIT @Matt:

I can only assume that the Count() extension method for IEnumerable is doing something like this:

Yes, of course it does. This is what I meant. Actually, it uses ICollection instead of IList but the result is the same.


I just wrote up a quick test, try this:

 IEnumerable<Object> myList = new List<Object>();

 Stopwatch watch = new Stopwatch();

 int x;

 watch.Start();
 for (var i = 0; i <= 1000000; i++)
 {
    if (myList.Count() == 0) x = i; 
 }
 watch.Stop();

 Stopwatch watch2 = new Stopwatch();

 watch2.Start();
 for (var i = 0; i <= 1000000; i++)
 {
     if (!myList.Any()) x = i;
 }
 watch2.Stop();

 Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
 Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
 Console.ReadLine();

The second is almost three times slower :)

Trying the stopwatch test again with a Stack or array or other scenarios it really depends on the type of list it seems - because they prove Count to be slower.

So I guess it depends on the type of list you're using!

(Just to point out, I put 2000+ objects in the List and count was still faster, opposite with other types)


List.Count is O(1) according to Microsoft's documentation:
http://msdn.microsoft.com/en-us/library/27b47ht3.aspx

so just use List.Count == 0 it's much faster than a query

This is because it has a data member called Count which is updated any time something is added or removed from the list, so when you call List.Count it doesn't have to iterate through every element to get it, it just returns the data member.


The second option is much quicker if you have multiple items.

  • Any() returns as soon as 1 item is found.
  • Count() has to keep going through the entire list.

For instance suppose the enumeration had 1000 items.

  • Any() would check the first one, then return true.
  • Count() would return 1000 after traversing the entire enumeration.

This is potentially worse if you use one of the predicate overrides - Count() still has to check every single item, even it there is only one match.

You get used to using the Any one - it does make sense and is readable.

One caveat - if you have a List, rather than just an IEnumerable then use that list's Count property.