C#中实际的lambda类型是什么?

ig-*_*nyk 24 c# lambda func

我读到C#lambdas可以被非法转换为Action或Func,但是lambda不能直接执行定义lambda函数并立即执行它 例如:

int n = (()=>5)(); //doesn't work
int n = ((Func<int>)(()=>5))(); //works
Run Code Online (Sandbox Code Playgroud)

那么lambda的实际类型是什么?为什么不能直接调用它?是因为C#类型系统比Haskell或Scala系统"弱"吗?

小智 27

lambda表达式没有类型.它不能,因为它可能拥有的.NET世界中的任何类型,也会硬编码lambda的参数和结果的类型.现在考虑:

x => x + 1
Run Code Online (Sandbox Code Playgroud)

什么类型可以x?结果是什么类型的?这里没有任何单一的答案,以及lambda表达式的确可以转化成Func<int, int>,Func<double, double>以及许多其他委托类型使用不同的参数.给lambda表达式一个类型会禁止这样的表达式.C#确实想要允许这样的表达式,所以设计的不是给这样的表达式任何类型.

  • 我不确定你想到的是什么样的代码示例,我想要添加的是表达式可以转换为的委托类型的示例,我现在已经将其包含在答案中. (2认同)
  • 作为另一个例子,在`静态List <string> AppendOnes(List <string> li){return li.ConvertAll(x => x + 1); 箭头成为`System.Converter <string,string>`的一个实例.从历史上看,泛型委托`Converter <,>`在BCL之前存在"funcs",即类型族`Func <>`,`Func <,>`,`Func <,,>`等. (2认同)

Sel*_*enç 9

这是因为() => 5可以与各种委托类型兼容(例如,您可能有一个delegate不带任何东西并返回的自定义int).并且为了创建一个delegate,编译器必须知道确切的类型.它不能只选择适合您需求的随机类型.所以这就是为什么除非你把它转换为实际的委托类型,否则你不能Invoke.

在方法期望a的情况下delegate,编译器隐式地完成转换:

void Foo(Func<int> func) {  }

Foo(() => 5); 
Run Code Online (Sandbox Code Playgroud)

同样重要的是要知道delegates实际上是幕后的课程.每次创建delegate实例时,编译器都会创建一个实例class.因此,无论哪种方式,您都必须指定一个类型,以便编译器知道要使用哪种类型.