Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lambda表达式-C#编译器推理_C#_Expression Trees_Type Inference - Fatal编程技术网

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

Lambda表达式-C#编译器推理,c#,expression-trees,type-inference,C#,Expression Trees,Type Inference,我试图理解编译器的推理行为。例如,在下面的代码段中,已编译委托的运行时类型为Func 但下面的代码行不编译。不确定编译器将其隐式转换为Expression并将变量赋值为LambdaExpression类型时,这里有什么不明确的地方 LambdaExpression lambdaExp2 = ()=>2+1; 我能猜到的一个可能的原因是,右边的lambda表达式也可能匹配我的自定义委托的签名,在这种情况下,编译器无法推断委托类型。但同样的原因也适用于我最初的代码片段。为什么CLR(运行时)

我试图理解编译器的推理行为。例如,在下面的代码段中,已编译委托的运行时类型为
Func

但下面的代码行不编译。不确定编译器将其隐式转换为
Expression
并将变量赋值为LambdaExpression类型时,这里有什么不明确的地方

LambdaExpression lambdaExp2 = ()=>2+1;

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

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

delegate int del();
当第一个代码段中的表达式与此委托的签名匹配时,无法将其转换为此类型,因为
LambdaExpression
返回匿名类型:

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
表达式exp=()=>2+1; LambdaExpression lambdaExp2=exp; var compiled2=lambdaExp2.Compile(); var mydel2=compiled2为del;//这会奏效的
我认为您将匿名lambda和委托与命名的lambda和委托混合在一起;考虑以下声明:

delegate int del();
当第一个代码段中的表达式与此委托的签名匹配时,无法将其转换为此类型,因为
LambdaExpression
返回匿名类型:

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
表达式exp=()=>2+1; LambdaExpression lambdaExp2=exp; var compiled2=lambdaExp2.Compile(); var mydel2=compiled2为del;//这会奏效的
首先,让我以更简洁的形式重新陈述这个问题

lambda表达式可以转换为
expression
,其中
T
是与lambda表达式兼容的委托类型<代码>表达式源自
LambdaExpression
。那么,为什么我们不能将lambda表达式直接转换为
LambdaExpression

原因是:因为这是C#中罕见的情况之一,类型信息从分配目标的类型流向被分配对象的类型。转换lambda时,编译器必须知道委托类型C#编译器不会从lambda推断委托类型,而是验证lambda是否与给定委托类型兼容

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

但是对于“为什么这个功能不存在?”这个问题的答案总是一样的我们不需要给出不实施功能的理由。没有人要求提供该功能,也没有人设计、实施、测试或将其交付给客户。因此,没有特征


相反,不存在的特性需要倡导者开始将它们转换为现有特性。如果这是您想要或需要的功能,那么请在github论坛上讨论并宣传该功能。或者自己实施,;编译器是开源的。

让我以更简洁的形式重新说明这个问题

lambda表达式可以转换为
expression
,其中
T
是与lambda表达式兼容的委托类型<代码>表达式源自
LambdaExpression
。那么,为什么我们不能将lambda表达式直接转换为
LambdaExpression

原因是:因为这是C#中罕见的情况之一,类型信息从分配目标的类型流向被分配对象的类型。转换lambda时,编译器必须知道委托类型C#编译器不会从lambda推断委托类型,而是验证lambda是否与给定委托类型兼容

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

但是对于“为什么这个功能不存在?”这个问题的答案总是一样的我们不需要给出不实施功能的理由。没有人要求提供该功能,也没有人设计、实施、测试或将其交付给客户。因此,没有特征


相反,不存在的特性需要倡导者开始将它们转换为现有特性。如果这是您想要或需要的功能,那么请在github论坛上讨论并宣传该功能。或者自己实施,;编译器是开源的。

()=>2+1
可以被编译器翻译成
Func
Expression
,两者都不能隐式转换成
LambdaExpression
@haim770:
表达式
为什么不能隐式转换成
LambdaExpression
,它的基类?@EricLippert,我没有注意到它实际上是基类。你说得对。加速了lambda表达式编译和静态类型推断的实现<代码>()=>2+1可以由编译器转换为
Func
Expression
,并且两者都不能隐式转换为
LambdaExpression
@haim770:为什么
表达式