Lambda 表达式 - C# 编译器推理

Lambda Expression - C# compiler inference

我正在尝试了解编译器推理行为。例如,从下面的代码片段中,运行 编译委托的时间类型是 Func<int>

Expression addExpr = Expression.Add(Expression.Constant(2), Expression.Constant(1));
LambdaExpression lambdaExpr1 = Expression.Lambda(addExpr, null);
var compiled = lambdaExpr1.Compile();

但是下面的代码行无法编译。不确定编译器将其隐式转换为 Expression<Func<int>> 并分配给变量以键入 LambdaExpression

有什么歧义
LambdaExpression lambdaExp2 = ()=>2+1;

我猜到右侧的 lambda 表达式也可能与我的自定义委托的签名匹配,在这种情况下编译器无法推断委托类型的一个可能原因。但同样的原因适用于我的初始代码片段。为什么CLR(运行time)可以决定它可以是Func<int>类型。如果这是可能的,并且到 运行 时间足够接近推理,那么为什么 c# 编译器不能做同样的事情。

我认为您将匿名 lambda 和委托与命名的混合在一起;考虑以下声明:

delegate int del();

虽然您在第一个片段中的表达式与此委托的签名匹配,但您无法将其转换为此类型,因为 LambdaExpression returns 匿名类型:

var mydel = compiled as del; // Returns null

另一方面,如果您从类型化委托构建表达式,即使在编译后它仍将保留签名:

Expression<del> exp = () => 2 + 1;
LambdaExpression lambdaExp2 = exp;
var compiled2 = lambdaExp2.Compile();

var mydel2 = compiled2 as del; // This will work

让我首先以更简洁的形式重新陈述问题。

A lambda expression can be converted to Expression<T> where T is a delegate type compatible with the lambda expression. Expression<T> is derived from LambdaExpression. Why then can we not convert a lambda expression directly to LambdaExpression?

原因是:因为这是 C# 中类型信息从赋值目标的 type 流向赋值目标的 type 的罕见情况之一正在分配的东西。转换 lambda 时,编译器必须知道委托类型; C# 编译器不会从 lambda 中推导出委托的类型,而是验证 lambda 是否与给定的委托类型兼容

现在,我们是否可以设计并实现一个系统,如果类型信息不存在,并且转换目标是 LambdaExpression,那么可以做出合理的猜测?当然。除了没有人想要或需要该功能外,没有什么能阻止我们。

但是问题"why doesn't this feature exist?"的答案总是一样的。 我们不需要给出不实现功能的理由。没有人要求该功能,没有人设计、实施、测试或将其发送给客户。因此,没有特征。

相反,不存在的功能需要倡导者开始将它们变成现有功能。如果这是您想要或需要的功能,请在 github 论坛上发布并宣传该功能。或者自己实现;编译器是开源的。