我读到C#lambdas可以被非法转换为Action或Func,但是lambda不能直接执行Define a lambda function and execute it immediately 例如:
int n = (()=>5)(); //doesn't work
int n = ((Func<int>)(()=>5))(); //works
那么lambda的实际类型是什么?为什么不能直接调用它?是因为C#类型系统比Haskell或Scala系统“弱”吗?
答案 0 :(得分:27)
lambda表达式没有类型。它不能,因为它可能拥有的.NET世界中的任何类型,也会硬编码lambda的参数和结果的类型。现在考虑:
x => x + 1
x
可以使用哪种类型?结果是什么类型的?没有任何单一答案,lambda表达式确实可以转换为Func<int, int>
,Func<double, double>
和许多其他具有不同参数的委托类型。给lambda表达式一个类型会禁止这样的表达式。 C#确实想要允许这样的表达式,所以设计的不是给这样的表达式任何类型。
答案 1 :(得分:9)
这是因为() => 5
可以与各种代理类型兼容(例如,您可能拥有一个不带任何内容并返回delegate
)的自定义int
。并且为了创建delegate
,编译器必须知道确切的类型。它不能选择适合您需求的随机类型。这就是为什么除非你将它转换为实际的委托类型,否则你不能Invoke
它。
在方法需要delegate
的情况下,编译器会隐式完成转换:
void Foo(Func<int> func) { }
Foo(() => 5);
同样重要的是要知道delegates
实际上是幕后的类。每次创建delegate
实例时,编译器都会创建该class
的实例。因此,无论哪种方式,您都必须指定一个类型,以便编译器知道要使用哪种类型。