简体   繁体   English

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

[英]Can I ignore delegate parameters with lambda syntax?

I am curious why C# allows me to ignore delegate parameters in some cases but not others. 我很好奇为什么C#允许我在某些情况下忽略委托参数而不是其他情况。

For instance this is permitted: 例如,这是允许的:

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

but this is not: 但这不是:

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

Is there a way to initialize a delegate and ignore the parameters using a lambda? 有没有办法初始化委托并使用lambda忽略参数? I know that I can add a single parameter to the lambda and fix the previous line but this is more of an academic question pertaining to the compiler and why or how this works. 我知道我可以在lambda中添加一个参数并修复前一行,但这更像是一个与编译器有关的学术问题,以及为什么或如何工作。

I believe that your first sample actually creates an anonymous function that is able to take on many different signatures whose body is the single statement Console.WriteLine... . 我相信你的第一个样本实际上创建了一个匿名函数,它能够采用许多不同的签名,其主体是单个语句Console.WriteLine... Because it can match different signatures, it does not cause a problem. 因为它可以匹配不同的签名,所以它不会导致问题。 In the second sample, the lambda syntax itself defines a function that takes no parameters with the same body. 在第二个示例中,lambda语法本身定义了一个函数,该函数不使用同一主体的参数。 Obviously the latter is not consistent with the defined Action so you get the error. 显然,后者与定义的Action不一致,因此您会收到错误。

C# Anonymous Method Reference C#匿名方法参考

There is one case in which an anonymous method provides functionality not found in lambda expressions. 有一种情况是匿名方法提供lambda表达式中没有的功能。 Anonymous methods enable you to omit the parameter list, and this means that an anonymous method can be converted to delegates with a variety of signatures. 匿名方法使您可以省略参数列表,这意味着可以将匿名方法转换为具有各种签名的委托。 This is not possible with lambda expressions. lambda表达式无法做到这一点。

To elaborate on tvanfosson's answer; 详细说明tvanfosson的答案; this behavior is described in the C# 3.0 language specification (§7.14): C#3.0语言规范(第7.14节)中描述了此行为:

The behavior of lambda-expressions and anonymous-method-expressions is the same except for the following points: 除了以下几点之外,lambda表达式和anonymous-method-expressions的行为是相同的:

• anonymous-method-expressions permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters. •anonymous-method-expressions允许完全省略参数列表,从而产生可转换性以委托任何值参数列表的类型。

• lambda-expressions permit parameter types to be omitted and inferred whereas anonymous-method-expressions require parameter types to be explicitly stated. •lambda-expressions允许省略和推断参数类型,而anonymous-methods-expressions需要明确声明参数类型。

• The body of a lambda-expression can be an expression or a statement block whereas the body of an anonymous-method-expression must be a statement block. •lambda表达式的主体可以是表达式或语句块,而anonymous-method-expression的主体必须是语句块。

• Since only lambda-expressions can have an expression body, no anonymous-method-expression can be successfully converted to an expression tree type (§4.6). •由于只有lambda表达式可以具有表达式主体,因此不能将anonymous-method-expression成功转换为表达式树类型(第4.6节)。

I think: 我认为:

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

is the equivalent of: 相当于:

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

which wouldn't compile either. 这也不会编译。 As Daniel Plaisted says () is explicitly saying there aren't any parameters. 正如Daniel Plaisted所说()明确表示没有任何参数。

If there were an equivalent of delegate{} it might be: 如果有一个等同的委托{},它可能是:

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

Which isn't very pretty and I suspect it suspect isn't in the spirit of lambda expressions. 这不是很漂亮,我怀疑它不符合lambda表达的精神。

As others said, no, you can't skip declaring the parameters to a lambda. 正如其他人所说,不,你不能跳过将参数声明为lambda。 But, for cleanliness, I suggest giving them a name such as _. 但是,为了清洁,我建议给他们一个名字,如_。 For example 例如

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

You aren't ignoring them per-se, but you're indicating you don't care what they are and will not use them. 你并没有忽视它们,但是你表明你不关心它们是什么,也不会使用它们。

The () => ... syntax explicitly specifies that the lambda takes no parameters. ()=> ...语法显式指定lambda不带参数。 Perhaps the language could be modified so that () => really meant "Infer the parameters of this lambda for me" in the same way the delegate syntax does, but that would make the language more complicated. 也许语言可以被修改,以便()=>真正意味着“为我推断这个lambda的参数”,就像委托语法一样,但这会使语言更复杂。 When designing new language features, you start at minus 100 , and I don't think this one passes the test. 在设计新的语言功能时, 你从零开始 ,我不认为这个通过测试。

There may also be more technical reasons why this would be difficult to implement (which is probably more in line with what you were asking for, but I doubt the technical reasons drove this decision if it ever came up). 可能还有更多的技术原因导致难以实现(这可能更符合您的要求,但我怀疑技术原因是否会导致这一决定出现)。

Actually, delegate {} does not specify any parameters and fits any delegate method signature - therefore it is permitted in your first construcion. 实际上,委托{}没有指定任何参数并且适合任何委托方法签名 - 因此在第一个构造中允许它。

The Lambda expression () => ...; Lambda表达式()=> ...; specifically states parameterless delegate, which contradicts the signature required by Action - a delegate with single parameter. 特别声明无参数委托,它与Action所需的签名相矛盾 - 具有单个参数的委托。

You may want to use one of the following options. 您可能想要使用以下选项之一。

If you need the action to have a parameter, you can do it the next way ("_" is a legal character for identifier name). 如果您需要操作来获取参数,则可以采用下一种方式(“_”是标识符名称的合法字符)。

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

Or you may want to use parameterless Action as follows: 或者您可能希望使用无参数Action,如下所示:

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

I'd say it's to have a forced use of the parameters of the lambda expression. 我要说是强制使用lambda表达式的参数。

Take your first example, how would you interact with the passed in value, there's no local representation of it. 拿你的第一个例子,你将如何与传入的值进行交互,它没有本地表示。

What about this? 那这个呢?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM