ChatGPT解决这个技术问题 Extra ChatGPT

为什么我不能在 lambda 表达式中使用空传播运算符?

我经常在我的代码中使用 null 传播运算符,因为它为我提供了更具可读性的代码,特别是在长查询中,我不必对使用的每个类进行 null 检查。

下面的代码抛出一个编译错误,我们不能在 lambda 中使用空传播运算符。

var cnt = humans.AsQueryable().Count(a => a.House?[0].Price == 5000);

错误 :

错误 CS8072 表达式树 lambda 可能不包含空传播运算符。

如果真的不能做任何其他事情,C# 可以轻松地将上面的代码转换为下面的代码!

var cnt = humans.AsQueryable().Count(a => a.House != null && a.House[0].Price == 5000);

我很好奇为什么 C# 什么都不做,只是抛出编译器错误?

Foo?.Bar 不等同于 Foo != null ? Foo.Bar : null,因为 Foo 使用 null 传播运算符计算一次,然后使用条件计算两次,因此翻译并非在所有情况下都是正确的。
请注意,如果它的代码用于 EF,那么您可能并不真正需要 null 传播运算符,因为当查询转换为 SQL 调用时,SQL 不会抛出 null :-)
注意: 编写 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)"}; 而不必编写 ProductName = (p == null) ? "(No products)" : p.ProductName 也很有用,因为 EF 当前不支持 ?. 运算符。

G
Gabe

这很复杂,因为表达式树 lambdas(与委托 lambdas 不同)由尚不支持 null 传播的现有 LINQ 提供程序解释。

转换为条件表达式并不总是准确的,因为有多个评估,而使用 ?. 只有一个评估,例如:

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

您可以深入了解相关的 discussion on CodePlex,其中提供了 3 种解决方案:NullPropagationExpressionConditionalExpression &混合动力车


如果某些查询提供程序不支持它,我当然不会感到惊讶,但这不是 C# 语言不支持它的理由。
某些查询提供者还不支持它的事实并不是禁止所有查询提供者使用它的理由。
显然,在该提供者的用户能够真正创建表示它的表达式树之前,没有任何查询提供者会花时间来支持处理这样的请求。要支持这一点,首先需要让 lambdas 能够表示它。之后,查询提供者可以开始支持它,因为他们认为这是合适的。也有很多供应商在做各种不同的事情。 EF 并不是世界上唯一的查询提供程序。
Expression 的整个point 是能够在语义上将所有 C# 表达式表示为代码。它的设计目的不仅仅是语言的一小部分。
看起来这个问题在 3 年后仍然没有解决 - 微软现在不应该能够找到时间吗?如今,他们似乎有一个坏习惯,即以时间和资源为借口,在 C# 中实现了一半的新功能。