我可以使用lambda语法忽略委托参数吗?
我很好奇为什么C#允许我在某些情况下忽略委托参数,而不是其他情况。我可以使用lambda语法忽略委托参数吗?
例如,这是允许的:
Action<int> action = delegate { Console.WriteLine("delegate"); };
但这不是:
Action<int> action =() => Console.WriteLine("lambda");
有没有一种方法来初始化一个委托,并使用Lambda忽略的参数?我知道我可以给lambda添加一个参数并修复上一行,但这更多的是与编译器有关的学术问题,以及它为什么或如何工作。
我相信你的第一个示例实际上创建了一个匿名函数,它能够接受许多不同的签名,其身体是单个语句Console.WriteLine...
。因为它可以匹配不同的签名,所以不会导致问题。在第二个示例中,lambda语法本身定义了一个不带相同主体的参数的函数。显然,后者与定义的Action不一致,所以你会得到错误。
有一种情况,其中一个 匿名方法提供在lambda 表达式没有发现 功能。匿名方法使您可以省略参数列表 ,并且 这意味着可以将具有 各种签名的匿名方法 转换为委托。对于lambda表达式,这不是 。
The()=> ...语法显式指定lambda不带参数。也许语言可以被修改,使得()=>真的意味着“为我推出这个lambda的参数”,就像委托语法一样,但是这会使语言更加复杂。在设计新的语言功能时,you start at minus 100,我不认为这个通过了测试。
可能还有更多的技术原因,为什么这将很难实现(这可能更符合你的要求,但我怀疑技术上的原因推动这个决定,如果它出现了)。
我想说它是强制使用lambda表达式的参数。
拿你的第一个例子,你将如何与传入的值进行交互,没有它的本地表示。
详细说明tvanfosson的答案;
λ-表达式和 匿名方法表达式的行为是 除了以下几点相同:
•匿名这种行为是在C#3.0语言规范(§7.14)中描述 - 方法表达式允许 参数列表被完全省略 ,产生可兑换为 委托类型的任何值列表 参数。
•拉姆达表达式允许参数 类型可以省略和推断 而 需要的参数类型是 明确说明匿名方法表达式。
•一个lambda表达式的主体可以 是一个表达式或语句块 而一个 匿名方法表达式的主体必须是 语句块。
•由于仅λ-表达式可以 具有表达体,没有 匿名方法表达可以是 成功地转换为一个 表达式树类型(§4.6)。
我想:
Action<int> action =() => Console.WriteLine("lambda");
是等价的:
Action<int> action = delegate() { Console.WriteLine("delegate"); };
这会也不编译。正如Daniel Plaisted所说()明确表示没有任何参数。
如果有委托的等效{}可能是:
Action<int> action = => Console.WriteLine("lambda")
这是不是很漂亮,我怀疑这怀疑是不是在lambda表达式的精神。
正如别人所说,不,你不能跳过声明参数为lambda。但是,为了清洁,我建议给他们一个像_这样的名字。例如
foo.Click += (_,__) => { ... }
你并不是无视它们,但你表示你不在乎它们是什么,也不会使用它们。
这是怎么回事?
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;
}
实际上,委托{}没有指定任何参数并且适合任何委托方法签名 - 因此它在您的第一个构造中是允许的。 Lambda表达式()=> ...;特别声明无参数委托,这与Action所要求的签名相抵触 - 具有单一参数的委托。
您可能想要使用以下选项之一。
如果您需要动作来获取参数,您可以采用下一种方式(“_”是标识符名称的合法字符)。
Action<int> action = _ => Console.WriteLine("lambda");
或者你可能需要使用参数的操作如下:
Action action =() => Console.WriteLine("lambda");
这是否是正确与否取决于你如何看答案。生成的IL是*绝对*仅用于采用int的方法。编译器*知道它试图将其转换为的编译时类型 - 如果将操作签名更改为“委托”,则会发生编译时错误。 – 2009-07-04 05:59:16
我的意思是(我想我说的)是通过在第一个示例中省略委托的参数列表,编译器在创建方法时填入它,以便它匹配所需的签名。 Lambda表达式不允许您省略参数列表 - 一个空列表推断不带参数的方法 - 因此会导致编译时错误。 – tvanfosson 2009-07-04 14:43:21