Why doesn't Any() work on a c# null object
Solution 1
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!
Solution 2
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()
.
Solution 3
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!
Solution 4
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);
Solution 5
Because Any() it is a extension method like this:
public static bool Any(this IEnumerable enumerable)
{
if (enumerable == null)
throw ArgumentNullException("enumerable");
...
}
Comments
-
DefenestrationDay almost 2 years
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.
Why does C# behave this way?
-
ocket8888 almost 8 yearsIt might be worth mentioning why making distinction between an empty collection and an uninitialized collection is important. The only thing I can think of is that it tells you if the collection is taking up space in memory, but then I'm hardly a C# guru.
-
Jesper Bischoff-Jensen about 6 yearsThere is no spoon
-
Brandon Barkley about 6 yearsThis is a good solution, but if you are doing it frequently, writing your own extension method that does precisely this would be cleaner, especially if you were embedding this into a ternary expression or some such.
-
Brandon Barkley about 6 yearsWhile this is correct, I believe these are outdated semantics. What someone typically wants out of an "Any()"/"Where()"/"Select()"/etc. call or even a "foreach" iteration for that matter is to know if there is anything there and to do something if there is something there. So much code waste exists on pointless instantiations or null checks. We got the ?. operator. Go full bore and give us decent null capabilities on extension methods.
-
Shockwaver almost 6 yearsBad bad bad idea, to help helpless progs... need to use a crumpy
(Source?.Any()).GetValueOrDefault()
to make a simple check for emptiness 'OR' not existence on astrict on
scenario... bad decision from the linq guys: they should always remember that their stuff is for people who know what they are doing and not for people who are clueless like me! :/ -
Jesse C. Slicer over 5 years
public static bool IsNullOrEmpty<T>(this IEnumerable<T> source) { return source?.Any() != true; }
similar toString.IsNullOrEmpty(stringything)
-
ToolmakerSteve over 5 yearsMinor opinion: personally I find
if (foo?.Any() == true)
easier to grasp than.. ?? false)
. The former in English is "if any is true then ..", whereas the latter is inherently a two-step logical statement; harder to paraphrase. Its something like "if any (but treat null as false) then ..". -
ToolmakerSteve over 5 yearsAlternative names for
AnyOrDefault
might beHasItems
or to be more explicitAnyAndNotNull
. And FWIW, "Default" in yourAnyOrDefault
would refer to Default for type of Source, i.e. "null" for an IEnumerable - has nothing to do with Boolean's default of "false". So the name is misleading, becauseAnyOrDefault
logically would mean "Any or null (because that is the default)", so would returntrue
for null. Which is obviously not what you mean. -
Pawel Cioch about 5 yearsIt should be called
HasItems()
now whether empty list or null the name still correct -
Veggivore over 4 yearsSo I wonder why there isn't a AnyOrDefault option then... to handle the "there is no spoon" scenario...
-
CodesInChaos over 4 years@Dscoduc You can use
?.Any() ?? false
or?.Any() == true
. Alternatively.OrEmpty().Any()
if you want to use the extension method from my answer. -
azurez27 over 4 years@Dscoduc I just use this extension to check if empty or null
public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) => list == null || !list.Any();