1

Using LINQ I want to check if myList != null and then perform a Where.

I know I can write

if (myList != null { myList.Where(p => p.x == 2 && p.y == 3); }

But I want to use: myList?.Where(p => p.x == 2 && p.y == 3);

Does this work?

If not, what are other elegant solutions you know?

Zen Zac
  • 136
  • 1
  • 9
  • By "LINQ query" do you mean query syntax? The `from x in y where z select w` syntax. – Sweeper Nov 08 '19 at 08:05
  • 1. Make it impossible that the list is ever null or 2. `myList?.Where(p => p.x == 2 && p.y == 3) ?? DEFAULT_VALUE;` where DEFAULT_VALUE may be an empty List. – Fildor Nov 08 '19 at 08:06
  • please show your list structure – mhd.cs Nov 08 '19 at 08:08
  • My question may have been unclear. I'm asking if myList?.Where() is a valid expression and if not, what are the alternatives – Zen Zac Nov 08 '19 at 08:10
  • `myList?.Where(p => p.x == 2 && p.y == 3);` should in fact only execute `.Where` when `myList` is not null. If your code is not letting you compile, I suspect your project is not configured to use C# 6.0 or higher – Kei Nov 08 '19 at 08:12
  • Yes, you can use `myList?.Where()` which will return null if `myList` is null. What is the question, because surely you're not asking us if that works when you could have typed it and hit F9 before you've asked this question. – Reinstate Monica Cellio Nov 08 '19 at 08:12
  • @ZenZac ah okay. Yes, it is a valid expression. When myList is null, myList?.Where() will return null without executing the .Where() – Kei Nov 08 '19 at 08:12
  • 1
    _"I'm asking if myList?.Where() is a valid expression"_ - Did your IDE mark it? Did your compiler spit out an error? Did it throw an exception while running? Did it not do what you expected it to do? If the answers to all these are "No", then it's "valid". – Fildor Nov 08 '19 at 08:13
  • @ZenZac It's valid. Does it do what you want? No idea. – ProgrammingLlama Nov 08 '19 at 08:14

2 Answers2

7

Yes, list?.Where(i => i > 1) is a legit expression, which called "null propagation operator".

On of the problem of using null propagation operator is that you will start writing code like this

var result = list?.Where(i => i > 1)?.Select(i => i * 2)?.Where(i => i % 2 == 0)?.ToList();
// result can be null and still requires check for null

.. what are other elegant solutions you know?

Other elegant solution would be to make sure that whenever function returns a collection it never return null but an empty collection.

Such convention will make your code easier to read and understand actual intentions of the code, make it easy to test (less test cases to test), less "noisy null checks".

Notice that LINQ extension methods never return null.

If you are using libraries which returns null for a collection but you don't have access to the code - "convert" null to an empty collection and continue using as valid collection.

var checkedList = givenList ?? Enumerable.Empty<int>();
checkedList.Where(i => i > 1).ToList();

If you find yourself doing this a lot, create an extension method.

public IEnumerable<T> EmptyIfNull(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();     
}

Usage

var result = givenList.EmptyIfNull().Where(i => i > 1).ToList();
Fabio
  • 31,528
  • 4
  • 33
  • 72
5

If you build using C# 6 / Visual Studio 2013 or later, you are allowed to write:

var result = myList?.Where(p => p.x == 2 && p.y == 3);

So if myList is null, Where is not evaluated and result will be null, else of type of the resulting query (IEnumerable<T> or IQueryable<T>).

Null-conditional operators

Also you can write:

var result = myList?.Where(p => p.x == 2 && p.y == 3) ?? someValue;

So if myList is null, result will be assigned by someValue.

Null-coalescing operator

You can check option in Project Settings > Build > Advanced options > Language version.

  • 2
    Small extension `var result = myList?.Where(p => p.x == 2 && p.y == 3) ?? someDefault;` will return a suitable default value if your list is null – Peter Smith Nov 08 '19 at 08:19
  • If the use of C# 6 is unavailable, one could also do: `(myList ?? someDefault).Where(...)` which doesn't require the use of the newer null conditional. – Kei Nov 08 '19 at 08:36