24

Often in C# I have to do this

if(x.Items!=null && x.Items.Any())
{ .... }

Is there a short cut on a collection ?

Ian Vink
  • 66,960
  • 104
  • 341
  • 555
  • 1
    You could create your extension method as stated here: http://stackoverflow.com/questions/41319/checking-if-a-list-is-empty-with-linq – Farhad Jabiyev Mar 06 '15 at 17:12
  • 1
    so what's the issue in checking this way? – Ehsan Sajjad Mar 06 '15 at 17:12
  • Why don't you just write your own extension method as Farhad stated? – Christo S. Christov Mar 06 '15 at 17:13
  • @Ehsan It complicates branch coverage, if you're monitoring that, and only typically get one of the null or empty collection case. – Rup Mar 06 '15 at 17:14
  • If you hit such case often instead on-off method you can create `EmptyIfNull` extension to convert `null` to empty sequence and allow all LINQ operation: `if(x.Items.EmptyIfNull().Any())...` – Alexei Levenkov Mar 06 '15 at 17:33
  • 2
    You should avoid having null collections in the first place. Ensure that all collection variables are always given a value, even if that value is empty, so that there is no need to check them for null later. – Servy Mar 06 '15 at 17:41
  • @Servy I'd still check them for null even if that was the case. You never know who is going to use that code in the future (and that's why I find `?.` so useful and am eager to have c# 6 out of CTP :-) ) – Jcl Mar 06 '15 at 17:49
  • 1
    @Jcl do you also check if type of result for `string Foo()` is `string`? :) If contract says "never returns null" you should not check for null - the only valid action in case of `null` would be to completely fail operation/process anyway... – Alexei Levenkov Mar 06 '15 at 17:54
  • @Jcl So your problem is that your unnecessary checking of null for values that will never be null is inconveniencing you. In that case, if it hurts when you do that, stop doing that. If the code assumes that the collection is non-null, don't constantly check for null. – Servy Mar 06 '15 at 17:55
  • @AlexeiLevenkov if there was a syntax construct to determine "reference type not allowed to be null", then I wouldn't... there *is* a syntax that says that a string must be of string type (that's the `string` part in `string Foo()`) :-) – Jcl Mar 06 '15 at 17:57
  • @Servy I don't check for null if the immediate code ensures that a variable will never be null (or I've asserted that in some way), but whenever I'm writing library code, I never assume (or try not-to assume) anything that is not directly specified in the code (e.g., if it comes from a parameter in a public API method) – Jcl Mar 06 '15 at 17:59
  • @Jcl If your methods aren't designed to support accepting `null` values for arguments, your callers should expect that passing a `null` value will result in an exception. When someone does something wrong *tell them* rather than trying to hide the fact that someone is writing broken code. – Servy Mar 06 '15 at 18:01
  • @Servy I've found many cases where null is a perfectly valid value for some methods, but not for others... many times I'd rather not have the API user be writing the null check everytime he's using the API and check it inside. Of course, one is free to design their APIs as they want, but most of the time, I'd rather check for null than throw... unless I **specifically** want it to throw a well-documented exception for null parameters. YMMV of course – Jcl Mar 06 '15 at 18:06

2 Answers2

82

In C# 6, you'll be able to write:

if (x.Items?.Any() == true)

Before that, you could always write your own extensions method:

public static bool NotNullOrEmpty<T>(this IEnumerable<T> source)
{
    return source != null && source.Any();
}

Then just use:

if (x.NotNullOrEmpty())

Change the name to suit your tastes, e.g. NullSafeAny might be more to your liking - but I'd definitely make it clear in the name that it's a valid call even if x is null.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    In the C# 6 example do you have to do == true - or would if (x.Items?.Any()) work and if true would drop into that block - arguably only saves a few keystrokes and possibly == true makes it more clear – Ctrl_Alt_Defeat Mar 12 '18 at 14:37
  • 13
    @Ctrl_Alt_Defeat: No, `x.Items?.Any()` has a type of `Nullable`, so you need the `== true` here - that means the condition *won't* be met if `x.Items` returns `null`. That's not the same as `if (x.Items?.Any != false)` where if `x.Items` is null, the result will be null, which isn't equal to false, so the condition *would* be met. – Jon Skeet Mar 12 '18 at 14:51
  • thanks for clarifying – Ctrl_Alt_Defeat Mar 12 '18 at 15:56
  • 1
    And if you really wanted to avoid the nullable for other reasons: x.Items?.Any()??false – Adam Bezverkov Aug 10 '18 at 21:06
  • 1
    now let's make it hot: public static bool NotNullOrEmpty(this IEnumerable source) => source != null && source.Any(); – Sergey Zykov Apr 29 '19 at 14:04
  • @SergeyZykov: The whole point of that method declaration is for what you'd write *before C# 6*. – Jon Skeet Apr 29 '19 at 14:08
  • 1
    @JonSkeet correct, i think i'm just not fun of `== true` statements when dealing with nullable types. and that one `(myVar?.Any()).HasValue` doesn't feel right to me also. my personal taste to go maybe more verbose... but have a better readability. – Sergey Zykov Apr 29 '19 at 14:36
  • @SergeyZykov in this case using - Any() == true - as jon did it's showing clearly from Microsft .NET Reference (if the null it will throw argumentNull error showed below): https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,8788153112b7ffd0: public static bool Any(this IEnumerable source) { if (source == null) throw Error.ArgumentNull("source"); using (IEnumerator e = source.GetEnumerator()) { if (e.MoveNext()) return true; } return false; } – Sergio Rezende Feb 20 '20 at 15:22
  • @JonSkeet regarding that use under c# version 6 Microsoft says : https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to – Sergio Rezende Feb 20 '20 at 16:27
  • @JustFair: I'm afraid I don't understand your comment - could you rephrase it please? – Jon Skeet Feb 20 '20 at 16:39
  • In case that anyone needs to validate AS NULL using Jon´s approach DO NOT use: plants?.Any() == false !!! Use instead: plants?.Any() != true! – Sergio Rezende Feb 20 '20 at 16:40
  • @JonSkeet you said "in C# 6" you can do: if (x.Items?.Any() == true) but that is also regarding .NET Framwork 4.0 for example. – Sergio Rezende Feb 20 '20 at 16:56
  • 3
    @JustFair: Yes, I very specifically referred to C# rather than .NET. You can do it in .NET 2.0 - if you're using a C# 6 or higher compiler. But you *can't* do it using C# 5. Language and framework versions are not the same. – Jon Skeet Feb 20 '20 at 17:10
  • 1
    @JonSkeet, indeed. Anyway, any extra information as i presented may be useful for someone else on this community. I am up-voting this comment and your answer! – Sergio Rezende Feb 20 '20 at 17:18
  • isn't the function name should be HasAny or NotNullAndNotEmpty – Imran Rizvi Jul 30 '21 at 10:33
1

I also do a check on items of the list to assure the list not just contains all null objects; so as enhancement to Jon Skeet answer:

public static bool NotNullOrEmpty<T>(this IEnumerable<T> source)
{
    return source != null && !source.All(x => x == null);
}
alsafoo
  • 778
  • 4
  • 18
  • I personally find this confusing for the name (and definitely not equivalent to the OPs code). I'd expect to find if the list itself is not null and the list is not empty, not check if all items are null. Plus, this would more likely enumerate the whole enumerable so performance might suffer a lot depending on the list. You are free to have that check if it suits you, of course, but as a general solution (in, e.g., a library of extension methods) I'd recommend heavily against it. – Jcl Mar 06 '15 at 17:30
  • @Jcl if you go with Jon answer, the follow will result to true `var x = new List {null};` – alsafoo Mar 06 '15 at 17:34
  • yes, and that's what I'd be expecting. Not just with Jon Skeet's answer, but also with the OPs code – Jcl Mar 06 '15 at 17:36
  • I consider a list with only one item that's null, is empty list. what you think? – alsafoo Mar 06 '15 at 17:38
  • I agree with you though it is a performance hit. – alsafoo Mar 06 '15 at 17:40
  • I don't... the list **DOES** contain an object. The list is defined (i.e., not null) and it does contain one object of its defined type (so the list is "Not-Null-Or-Empty"). That's what I'd be checking... the value of the object is indifferent to me when I'm checking *the list* and not what it *contains*. I might have a check for nulls later (or not), but the fact that an object is null could mean one thing or another depending on its type and the intended usage of that type: you can't be sure of that if you are doing a *generic* extension method. – Jcl Mar 06 '15 at 17:40
  • Yes, but it is null object. what you gonna do with a list that ONLY contain a null object? this list is not useful to me. It is same as empty list. – alsafoo Mar 06 '15 at 17:44
  • 1
    `foreach(var x in myList) { if(x == null) DoThis(); else DoThat(); }`. If you use your method to check whether you should "foreach or not", then `DoThis()` would never be called. Imagine your list comes from a database and `null` values means "this order is not paid" so you "might" need to act upon `null` values (not the best example, but makes the point). Null values could mean something for some implementations... as I said, if it works for -your- type, then fine, but as a -generic- implementation, it has potential drawbacks. – Jcl Mar 06 '15 at 17:45
  • 2
    You could of course name your extension method `NotNullAndAnyHasValue()` or something, but I wouldn't **replace** the other extension method for this – Jcl Mar 06 '15 at 17:55