我很好奇为什么C#允许我在某些情况下忽略委托参数而不是其他情况。
例如,这是允许的:
Action<int> action = delegate { Console.WriteLine("delegate"); };
但这不是:
Action<int> action = () => Console.WriteLine("lambda");
有没有办法初始化委托并使用lambda忽略参数?我知道我可以在lambda中添加一个参数并修复上一行,但这更像是一个与编译器有关的学术问题,以及它的工作原理和方法。
答案 0 :(得分:18)
我相信您的第一个示例实际上创建了一个匿名函数,该函数能够采用其主体为单个语句Console.WriteLine...
的许多不同签名。因为它可以匹配不同的签名,所以它不会导致问题。在第二个示例中,lambda语法本身定义了一个函数,该函数不使用同一主体的参数。显然,后者与定义的Action不一致,因此您会收到错误。
有一个案例,其中一个 匿名方法提供 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");