Why doesn't Any() work on a c# null object

63,011

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 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). Renamed to 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");
    ...
}
Share:
63,011
DefenestrationDay
Author by

DefenestrationDay

iOS &amp; WPF developer

Updated on July 05, 2022

Comments

  • DefenestrationDay
    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
    ocket8888 almost 8 years
    It 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
    Jesper Bischoff-Jensen about 6 years
    There is no spoon
  • Brandon Barkley
    Brandon Barkley about 6 years
    This 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
    Brandon Barkley about 6 years
    While 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
    Shockwaver almost 6 years
    Bad 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 a strict 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
    Jesse C. Slicer over 5 years
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source) { return source?.Any() != true; } similar to String.IsNullOrEmpty(stringything)
  • ToolmakerSteve
    ToolmakerSteve over 5 years
    Minor 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
    ToolmakerSteve over 5 years
    Alternative names for AnyOrDefault might be HasItems or to be more explicit AnyAndNotNull. And FWIW, "Default" in your AnyOrDefault 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, because AnyOrDefault logically would mean "Any or null (because that is the default)", so would return true for null. Which is obviously not what you mean.
  • Pawel Cioch
    Pawel Cioch about 5 years
    It should be called HasItems() now whether empty list or null the name still correct
  • Veggivore
    Veggivore over 4 years
    So I wonder why there isn't a AnyOrDefault option then... to handle the "there is no spoon" scenario...
  • CodesInChaos
    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
    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();