ChatGPT解决这个技术问题 Extra ChatGPT

Why can't I use the null propagation operator in lambda expressions?

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.
Note that if its code for EF, there is the possibility that you don't really need the null propagating operator, because when a query is converted to SQL call, SQL doesn't throw nulls :-)
N.B.: It would also be useful to write 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.

G
Gabe

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


I would certainly not be surprised if certain query providers couldn't support it, but that's not a reason to not have the C# language support it.
The fact that certain query providers don't yet support it isn't a reason to prohibit all query providers from ever being able to use it.
And obviously no query provider is going to take the time to support handling such a request until users of that provider would be able to actually create expression trees that represent it. For this to be supported, the first thing that needs to happen is for lambdas to be able to represent it. After that exists, query providers can begin to support it, as they feel it is appropriate. There are also lots of providers out there doing all sorts of different things. It's not like EF is the only query provider in the world.
The whole point of 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.
Seems like this still isn't resolved 3 years later - shouldn't Microsoft have been able to find the time by now? They seem to have a bad habit of using time and resources as an excuse for half-implementing new features in C# these days.