When calling Any() on a null object, it throws an ArgumentNullException in C#. If the object is null, there definitely aren\'t \'any\', and it should probably return false.
With modern C#, you can easily handle the OP's scenario with a simple check like this:
List<string> foo = null;
if (foo?.Any() ?? false)
{
DoStuff();
}
This is kinda like a lame AnyOrDefault(bool default)
implementation that the OP is expecting the Any()
extension method to do.
You could easily make this into an extension like this:
public static bool HasItems<T>(this IEnumerable<T> source)
{
return (source?.Any() ?? false);
}
Honestly, I don't really like the name Renamed to AnyOrDefault
for this since it won't ever make sense to pass in a default value (a default of true would probably be pretty mean to people reading code later).HasItems
, as suggested in the comments. This is a far better name!
Any()
is asking: "Does this box contain any items?"
If the box is empty, the answer is clearly no.
But if there is no box in the first place, then the question makes no sense, and the function complains: "What the hell are you talking about? There is no box."
When I want to treat a missing collection like an empty one, I use the following extension method:
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
return sequence ?? Enumerable.Empty<T>();
}
This can be combined with all LINQ methods and foreach
, not just .Any()
.
When dealing with reference types, a null
value is semantically different from an "empty" value.
A null
string is not the same as string.Empty
, and a null
IEnumerable<T>
is not the same as Enumerable.Empty<T>
(or any other "empty" enumerable of that type).
If Any
were not an extension method, calling it on null
would result in NullReferenceException
. Since it is an extension method, throwing some exception (although not necessary) is a good idea because it preserves the well-known semantics of trying to call a method on null
: BOOM!
Any()
is an extension method, so this
is actually passed as the first argument to the method. In this situation, it's understandable for it to throw ArgumentNullException
is this
is null
.
You can perform the check yourself beforehand:
bool hasAny = yourData == null ? false : yourData.Any(yourPredicate);
Any()
is an extension method that throws ArgumentNullException
if the source is null. Would you perform an action on nothing? In general, it's better to get some explicit indicator of what's happening in the code rather than the default value.
But it doesn't mean it can't be like that. If you know what you doing, write your own custom implementation.
I just wanted to share with you some practical advice my company is following.
We write our custom packages shared with private NuGet that are widely used in our products. Checking if the list is null/empty is very frequent, so we decided to write our implementation of Any
which makes our code shorter and simpler.
Because Any() it is a extension method like this:
public static bool Any(this IEnumerable enumerable)
{
if (enumerable == null)
throw ArgumentNullException("enumerable");
...
}