Does C# have IsNullOrEmpty for List/IEnumerable?
Solution 1
nothing baked into the framework, but it's a pretty straight forward extension method.
/// <summary>
/// Determines whether the collection is null or contains no elements.
/// </summary>
/// <typeparam name="T">The IEnumerable type.</typeparam>
/// <param name="enumerable">The enumerable, which may be null or empty.</param>
/// <returns>
/// <c>true</c> if the IEnumerable is null or empty; otherwise, <c>false</c>.
/// </returns>
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
{
return true;
}
/* If this is a list, use the Count property for efficiency.
* The Count property is O(1) while IEnumerable.Count() is O(N). */
var collection = enumerable as ICollection<T>;
if (collection != null)
{
return collection.Count < 1;
}
return !enumerable.Any();
}
Daniel Vaughan takes the extra step of casting to ICollection (where possible) for performance reasons. Something I would not have thought to do.
Solution 2
Late update: since C# 6.0, the null-propagation operator may be used to express concise like this:
if ( list?.Count > 0 ) // For List<T>
if ( array?.Length > 0 ) // For Array<T>
or, as a cleaner and more generic alternative for IEnumerable<T>
:
if ( enumerable?.Any() ?? false )
Note 1: all upper variants reflect actually IsNotNullOrEmpty
, in contrast to OP question (quote):
Because of operator precedence
IsNullOrEmpty
equivalents look less appealing:
if (!(list?.Count > 0))
Note 2: ?? false
is necessary, because of the following reason (summary/quote from this post):
?.
operator will returnnull
if a child member isnull
. But [...] if we try to get a non-Nullable
member, like theAny()
method, that returnsbool
[...] the compiler will "wrap" a return value inNullable<>
. For example,Object?.Any()
will give usbool?
(which isNullable<bool>
), notbool
. [...] Since it can't be implicitly casted tobool
this expression cannot be used in theif
Note 3: as a bonus, the statement is also "thread-safe" (quote from answer of this question):
In a multithreaded context, if [enumerable] is accessible from another thread (either because it's a field that's accessible or because it's closed over in a lambda that is exposed to another thread) then the value could be different each time it's computed [i.e.prior null-check]
Solution 3
There is nothing built in.
It is a simple extension method though:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if(enumerable == null)
return true;
return !enumerable.Any();
}
Solution 4
var nullOrEmpty = list == null || !list.Any();
Solution 5
Putting together the previous answers into a simple extension method for C# 6.0+:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;
Eric Yin
Updated on July 12, 2022Comments
-
Eric Yin almost 2 years
I know generally empty List is more prefer than NULL. But I am going to return NULL, for mainly two reasons
- I have to check and handle null values explicitly, avoiding bugs and attacks.
- It is easy to perform
??
operation afterwards to get a return value.
For strings, we have IsNullOrEmpty. Is there anything from C# itself doing the same thing for List or IEnumerable?
-
Aaron McIver over 12 yearsNo but adding an extension method is trivial.
-
octothorpentine almost 9 yearspossible duplicate of How to check if IEnumerable is null or empty?
-
Jon Hanna over 12 yearsCaution must be taken though that the call to
enumerable.Any()
can lose an element of a non-rewindable enumeration. You can wrap it in something that'll keep track of that first element (and handle null nicely of course or we negate the OP's whole issue), but it can be handier in some cases to coalesce with an empty enumeration and just use the result. -
Patrick Szalapski almost 12 yearsUh, am I daft or should the last line of that function be
return !enumerable.Any();
? I'll edit it. -
supercat almost 12 yearsShould one also try casting to non-generic
ICollection
, since anIEnumerable<Animal>
might be something like an instance ofList<Cat>
, which does not implementICollection<Animal>
but does implement non-genericICollection
? -
Ruutert over 11 yearsThis doesn't work for XmlNodeList? XmlNodeList is also implementing the IEnumerable interface, why doesn't work this?
-
AaronLS over 10 yearsCould you give me an example of a non-rewindable collection in .NET? I mean just name of an existing class in the framework, not asking you to give me an example implementation of one.
-
Jon Hanna over 10 years@AaronLS the result of most Linq queries.
-
AaronLS over 10 yearsWhat would be the concrete type in that case? I'm aware of IQueryable which isn't really a list until you try to ToList/foreach at which point it materialized. I imagine there is some intermediate concrete type for IQueryable that is a forward only data reader under the hood, so what you say makes sense, I just can't imagine where you'd actually encounter this problem. If you
foreach(var item in someQueryable)
would generate its own eneumerator, and then didsomeQueryable.Any()
would be a seperate query and wouldn't affect the current foreach enumerator AFAIK. -
AaronLS over 10 yearsNot challenging you, just trying to explain my confusion.
-
Jon Hanna over 10 years@AaronLS it would be a separate enumerator, which would require you to run the query again, which is bad enough. If it was cast to
IEnumerable
then even more so, as the query will have been lost. -
xmoex about 10 yearsas seen here: msdn.microsoft.com/en-us/library/bb337697%28v=vs.110%29.aspx (check remarks) "The enumeration of source is stopped as soon as the result can be determined." wich makes me think a cast to collection is unnecessary as enumerable.Any() should have O(1) as well. so why cast to a list if you don't really know it is a list?
-
Lee Grissom over 9 yearsThe comment about "IEnumerable.Count() is O(N)" is correct... but the code isn't doing that, it's calling
Any()
. Although it's still a good idea to cast so that you can avoid theGetEnumerator
andMoveNext
code under the hood when callingAny
. -
stannius about 8 yearsI wonder why both this and the accepted answer both missed the ! before the Any() call. That same bug got propagated into my team's source code.
-
PRMan about 8 yearsThis could now be written in one line: return a == null || ((a as ICollection)?.Count == 0) || !a.Any();
-
MikeT over 7 yearsCode only answers are not good answers, try adding a few lines explaining what the problem was and how your code fixes it
-
tytyryty over 7 yearsCasting to ICollection is correct and good practice in general. All Linq methods implementations use casting to optimize performance. However, in this case, it is not necessary at all, as Any method internally will just call MoveNext only once.
-
Lee Grissom over 7 yearsThis won't compile if list is IEnumerable.
-
Lee Grissom over 7 yearsI just realized that this solution omits a short-circuit for
IReadOnlyCollection
(which does not inherit from ICollection). -
Teodor Tite over 7 years@GrimR3 Yes, you're right: that's more strait to the question. I've written it like that to be inline with the quote/referece.
-
El Mac almost 6 yearsStupid out-of-topic-question: Why is
ICollection.Count
O(1) andIEnumerable.Count()
O(n)? I undestand the latter one, but why is a simple cast enough to make it O(1)? -
Admin almost 5 years@ElMac The spec of ICollection.Count is that the count is tracked, any implementation should return the count without iterating the values to calculate it on demand. But as another person said in comments, the same optimisation should also be called for IReadOnlyCollection. Also, LINQ.Any uses the optimisation on ICollection, but not on IReadOnlyCollection.
-
intrepidis over 4 yearsYou can check for 0 or 1 elements with this:
(myArray?.Length ?? 0) < 2