为什么c#不能使用内联匿名lambdas或委托?

我希望我能恰当地提出问题的标题。

在c#中,我可以使用lambdas(作为委托),或者使用较旧的委托语法来执行此操作:

Func fnHello = () => "hello"; Console.WriteLine(fnHello()); Func fnHello2 = delegate() { return "hello 2"; }; Console.WriteLine(fnHello2()); 

那么为什么我不能“内联”lambda或委托体,并避免在命名变量中捕获它(使其匿名)?

 // Inline anonymous lambda not allowed Console.WriteLine( (() => "hello inline lambda")() ); // Inline anonymous delegate not allowed Console.WriteLine( (delegate() { return "hello inline delegate"; })() ); 

在javascript中工作的示例(仅用于比较)是:

 alert( (function(){ return "hello inline anonymous function from javascript"; })() ); 

这会产生预期的警报框。

更新 :看起来你可以在C#中使用内联匿名lambda,如果你适当地进行转换,但是()的数量开始让它变得难以驾驭。

 // Inline anonymous lambda with appropriate cast IS allowed Console.WriteLine( ((Func)(() => "hello inline anonymous lambda"))() ); 

也许编译器无法推断匿名委托的sig知道你试图调用哪个Console.WriteLine()? 有谁知道为什么需要这个特定演员?

C#中的Lambdas没有类型,直到它们被用于将它们转换为委托或表达式类型的上下文中。 这就是你不能说的原因

 var x = () => "some lambda"; 

你可能会喜欢

http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part-two.aspx

http://blogs.msdn.com/ericlippert/archive/2007/01/12/lambda-expressions-vs-anonymous-methods-part-three.aspx

如果你给它一个类型转换似乎工作:

 String s = ((Func) (() => "hello inline lambda"))(); 

它没用吗? 不是完全。 拿下面的话:

 String s; { Object o = MightBeNull(); s = o == null ? "Default value" : o.ToString(); } 

现在考虑一下:

 String S = ((Func)(o => o == null ? "Default value" : o.ToString()) )(MightBeNull()); 

它有点难看,但它很紧凑。

当您编写Func = ... ,编译器知道它必须创建一个类型为Func的对象。 但是当您编写该委托内联时,编译器不知道它必须创建哪种类型的对象。

如上所述,可以得出一个明显的结论:只需明确地告诉编译器类型!

 Console.WriteLine( new Func( () => "Hello" )() ); 

UPDATE

好的,在我写答案的时候,你更新了你的post。 我相信我上面的回答已经回答了“为什么需要这种特定类型”的问题。 重申:因为编译器不知道要创建哪种类型的对象。

现在详细说明一下“ 编译器无法推断出匿名委托的sig ”部分。 你看,它不像JavaScript。 在C#中,没有通用的“函数”(或“方法”)类型。 每个代理必须具有明确指定的签名和类型名称。 当您创建委托时,编译器必须知道什么类型。

现在,我可以看到你如何暗示编译器可以动态地构造一个委托类型,就像它对匿名对象类型(又称new { a = 1, b = "xyz" } )一样。 但想一想:无论如何,这样的代表可能没用。 我的意思是,你不能将它传递给另一个方法,因为该方法必须首先声明它的类型的参数。 而且你可以用它来制作一个事件,因为你必须再次拥有一个命名类型。

这样的东西……

您可以对接受Delegate参数的方法使用内联lambda表达式。

但是有一个轻微的问题 – 如果参数被输入为基本的委托类型,则需要将其显式地转换为Delegate的特定派生(比如Action); 否则编译器会抱怨。

类似的问题:
Invoke调用中的匿名方法
匿名方法和委托