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

时间:2009-02-03 02:34:59

标签: c# delegates lambda

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

例如,这是允许的:

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

但这不是:

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

有没有办法初始化委托并使用lambda忽略参数?我知道我可以在lambda中添加一个参数并修复上一行,但这更像是一个与编译器有关的学术问题,以及它的工作原理和方法。

7 个答案:

答案 0 :(得分:18)

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

C# Anonymous Method Reference

  

有一个案例,其中一个   匿名方法提供   lambda中找不到的功能   表达式。匿名方法启用   你要省略参数列表,和   这意味着一个匿名方法   可以转换为具有的代表   各种签名。这不是   可以使用lambda表达式。

答案 1 :(得分:8)

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

  

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

     

•anonymous-method-expressions允许   要省略的参数列表   完全,屈服于兑换   委托任何值列表的类型   参数。

     

•lambda-expressions允许参数   要省略和推断的类型   而匿名方法表达式   需要参数类型   明确说明。

     

•lambda表达式的主体可以   是表达式或语句块   而一个人的身体   anonymous-method-expression必须是a   声明块。

     

•因为只有lambda表达式可以   有一个表达主体,没有   anonymous-method-expression可以   成功转换为   表达式树类型(§4.6)。

我想:

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

相当于:

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

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

如果有相应的委托{},则可能是:

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

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

答案 2 :(得分:5)

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

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

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

答案 3 :(得分:2)

()=&gt; ...语法显式指定lambda不带参数。也许可以修改语言,以便()=&gt;真的意思是“以我的方式推断这个lambda的参数”,就像委托语法一样,但这会使语言更复杂。在设计新的语言功能时you start at minus 100,我不认为这个功能通过了测试。

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

这个怎么样?

Func<int> 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;
}

答案 6 :(得分:0)

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

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

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

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

  

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

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

  

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