I often use null propagating operator in my code because it gives me more readable code, specially in long queries I don't have to null-check every single class that is used.
The following code throws a compile error that we can't use null propagating operator in lambda.
var cnt = humans.AsQueryable().Count(a => a.House?[0].Price == 5000);
The error :
Error CS8072 An expression tree lambda may not contain a null propagating operator.
C# Could easily translate above code to the code to following code if really can't do anything else!
var cnt = humans.AsQueryable().Count(a => a.House != null && a.House[0].Price == 5000);
I'm curious why C# does nothing and simply throws a compiler error?
Foo?.Bar
is not equivalent to Foo != null ? Foo.Bar : null
because Foo
is evaluated once with the null-propagating operator, and twice with the conditional, so the translation wouldn't be correct in all cases.
var q = from c in Categories join p in Products on c equals p.Category into ps from p in ps.DefaultIfEmpty() select new { Category = c, ProductName = (p?.ProductName)??"(No products)"};
instead of having to write ProductName = (p == null) ? "(No products)" : p.ProductName
because EF currently does not support the ?.
operator.
It's complicated since expression tree lambdas (unlike delegate lambdas) are interpreted by already existing LINQ providers which don't yet support null propagating.
Converting to a conditional expression is not always accurate as there are multiple evaluations while with ?.
there's only a single evaluation for example:
customer.Where(a => c.Increment()?.Name) // Written by the user
customer.Where(a => c.Increment() == null ? null : c.Increment().Name) // Incorrectly interpreted by an old LINQ provider
You can go deeper in the relevant discussion on CodePlex where 3 solutions are offered: NullPropagationExpression
, ConditionalExpression
& a hybrid
Success story sharing
Expression
is to be able to represent all C# expressions semantically as code. It's not designed to be just some small subset of the language.