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

C# 我可以用lambda语法忽略委托参数吗?,c#,delegates,lambda,C#,Delegates,Lambda,我很好奇为什么C#允许我在某些情况下忽略委托参数,而在其他情况下则不允许 例如,这是允许的: Action<int> action = delegate { Console.WriteLine("delegate"); }; Action-Action=delegate{Console.WriteLine(“delegate”);}; 但这不是: Action<int> action = () => Console.WriteLine("lambda"); A

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

例如,这是允许的:

Action<int> action = delegate { Console.WriteLine("delegate"); };
Action-Action=delegate{Console.WriteLine(“delegate”);};
但这不是:

Action<int> action = () => Console.WriteLine("lambda");
Action Action=()=>Console.WriteLine(“lambda”);
是否有方法初始化委托并使用lambda忽略参数?我知道我可以向lambda添加一个参数并修复前一行,但这更像是一个关于编译器的学术问题,以及为什么或如何工作。

the()=>。。。语法明确指定lambda不接受任何参数。也许可以修改语言,使()=>的真正意思是“为我推断这个lambda的参数”,就像委托语法那样,但这会使语言更加复杂。在设计新的语言特性时,我认为这一个不能通过测试


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

我认为这是强制使用lambda表达式的参数


以您的第一个示例为例,您将如何与传入的值交互,它没有本地表示。

我相信您的第一个示例实际上创建了一个匿名函数,它能够接受许多不同的签名,其主体是单个语句
控制台。WriteLine…
。因为它可以匹配不同的签名,所以不会引起问题。在第二个示例中,lambda语法本身定义了一个不接受具有相同主体的参数的函数。显然,后者与定义的操作不一致,因此您会得到错误

在一个案例中 匿名方法提供 在lambda中找不到功能 表达。匿名方法启用 您可以忽略参数列表,并且 这意味着一个匿名方法 可以使用 各种各样的签名。这不是 可能与lambda表达式有关


详细说明tvanfosson的回答;这种行为在C#3.0语言规范(§7.14)中有描述:

lambda表达式的行为和 匿名方法表达式是 除以下几点外,情况相同:

•匿名方法表达式允许 要省略的参数列表 完全是,允许兑换成人民币 任何值列表的委托类型 参数

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

•lambda表达式的主体可以 可以是表达式或语句块 而 匿名方法表达式必须是 语句块

•因为只有lambda表达式可以 有一个表情体,不是吗 匿名方法表达式可以是 已成功转换为 表达式树类型(§4.6)

我认为:

Action<int> action = () => Console.WriteLine("lambda");
Action Action=()=>Console.WriteLine(“lambda”);
相当于:

Action<int> action = delegate() { Console.WriteLine("delegate"); };
Action Action=delegate(){Console.WriteLine(“delegate”);};
也不会编译。正如Daniel Plaisted所说()明确表示没有任何参数

如果存在等效的委托{},则可能是:

Action<int> action = => Console.WriteLine("lambda")
Action 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;
}
Func lamdapointer=()=>TwoArgMethodThatReturnsInt(10,20);//不能对委托“NoArgmethodThatReturnsInt”调用相同的方法
lamdapointer();
委托int noargmethodthattreturnsint();
NoArgmethodThatReturnsInt del=NoArgmethodThatReturnsInt;//只有代表才能这样做
返回sint(int x,int y)的公共int-twoargmethod
{
返回x+y;
}
public int noargmethodthatthereturnsint()方法
{
返回20;
}

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

Lambda表达式()=>。。。;特别声明了无参数委托,这与操作所需的签名相矛盾-具有单个参数的委托

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

如果您需要操作具有参数,则可以采用下一种方法(“\u”是标识符名称的合法字符)

Action-Action=\u=>Console.WriteLine(“lambda”)

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

Action Action=()=>Console.WriteLine(“lambda”)


而且会让任何新加入lambdas或不熟悉您的惯例的人都感到困惑。任何新加入lambdas的人都需要经过培训才能参与我们的任何项目。这是一个招聘/培训/人力资源问题。我认为给那些会被简单的东西弄糊涂的人写信没有什么好处:)。我建议dummy1
dummy2
,等等都是更好的名字,因为像
\`这样的名字有时被用来表示有意义的事情(例如,
=someComplocatedExpression;\u1=(\u2+\u3)*(\u4+\u5)
[但第二个表达式更为复杂]。
\uu
这个名称相当清楚地指的是在上面一行中获得其引用的对象;属性的名称对于阅读代码的人来说往往比提供给属性的名称更有趣