我可以使用lambda语法忽略委托参数吗?

我很好奇为什么C#允许我在某些情况下忽略委托参数而不是其他情况。

例如,这是允许的:

Action action = delegate { Console.WriteLine("delegate"); }; 

但这不是:

 Action action = () => Console.WriteLine("lambda"); 

有没有办法初始化委托并使用lambda忽略参数? 我知道我可以向lambda添加一个参数并修复前一行,但这更像是一个与编译器有关的学术问题,以及为什么或如何工作。

我相信你的第一个样本实际上创建了一个匿名函数,它能够采用许多不同的签名,其主体是单个语句Console.WriteLine... 因为它可以匹配不同的签名,所以它不会导致问题。 在第二个示例中,lambda语法本身定义了一个函数,该函数不使用同一主体的参数。 显然,后者与定义的Action不一致,因此您会收到错误。

C#匿名方法参考

有一种情况是匿名方法提供lambda表达式中没有的function。 匿名方法使您可以省略参数列表,这意味着可以将匿名方法转换为具有各种签名的委托。 lambda表达式无法做到这一点。

详细说明tvanfosson的答案; C#3.0语言规范(第7.14节)中描述了此行为:

除了以下几点之外,lambda表达式和anonymous-method-expressions的行为是相同的:

•anonymous-method-expressions允许完全省略参数列表,从而可以转换为任何值参数列表的委托类型。

•lambda-expressions允许省略和推断参数类型,而anonymous-methods-expressions需要明确声明参数类型。

•lambda表达式的主体可以是表达式或语句块,而anonymous-method-expression的主体必须是语句块。

•由于只有lambda表达式可以具有表达式主体,因此不能将anonymous-method-expression成功转换为表达式树类型(第4.6节)。

我认为:

 Action action = () => Console.WriteLine("lambda"); 

相当于:

 Action action = delegate() { Console.WriteLine("delegate"); }; 

这也不会编译。 正如Daniel Plaisted所说()明确表示没有任何参数。

如果有一个等同的委托{},它可能是:

 Action action = => Console.WriteLine("lambda") 

这不是很漂亮,我怀疑它不符合lambda表达的精神。

正如其他人所说,不,你不能跳过将参数声明为lambda。 但是,为了清洁,我建议给他们一个名字,如_。 例如

 foo.Click += (_,__) => { ... } 

你并没有忽视它们本身,但你表明你不关心它们是什么,也不会使用它们。

()=> …语法显式指定lambda不带参数。 也许语言可以被修改,以便()=>真正意味着“为我推断这个lambda的参数”,就像委托语法一样,但这会使语言更复杂。 在设计新的语言function时, 你从零开始 ,我不认为这个通过测试。

可能还有更多技术原因导致难以实现(这可能更符合您的要求,但我怀疑技术原因是否会导致这一决定出现)。

我要说是强制使用lambda表达式的参数。

拿你的第一个例子,你将如何与传入的值进行交互,没有本地表示。

那这个呢?

 Func lamdapointer = () => TwoArgMethodThatReturnsInt(10,20); // the same method cannot be called with the delegate "NoArgmethodThatReturnsInt" lamdapointer(); Delegate int NoArgmethodThatReturnsInt(); NoArgmethodThatReturnsInt del = NoArgmethodThatReturnsInt; // only this is possible with delegates public int TwoArgMethodThatReturnsInt(int x,int y) { return x + y; } public int NoArgmethodThatReturnsInt() { return 20; } 

实际上,委托{}没有指定任何参数并且适合任何委托方法签名 – 因此在您的第一个构造中允许它。

Lambda表达式()=> …; 特别声明无参数委托,它与Action所需的签名相矛盾 – 具有单个参数的委托。

您可能想要使用以下选项之一。

如果您需要操作来获取参数,则可以采用下一种方式(“_”是标识符名称的合法字符)。

Action action = _ => Console.WriteLine("lambda");

或者您可能希望使用无参数Action,如下所示:

Action action = () => Console.WriteLine("lambda");