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

发布于 2024-07-12 07:37:14 字数 363 浏览 4 评论 0原文

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

例如,这是允许的:

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

但这不是:

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

有没有办法初始化委托并使用 lambda 忽略参数? 我知道我可以向 lambda 添加一个参数并修复前一行,但这更多是一个与编译器以及其工作原理或原理相关的学术问题。

I am curious why C# allows me to ignore delegate parameters in some cases but not others.

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? 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

空宴 2024-07-19 07:37:15

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

lambda 表达式的行为和
匿名方法表达式是
除了以下几点之外,其他相同:

• 匿名方法表达式允许
需要省略的参数列表
完全,可兑换为
任何值列表的委托类型
参数。

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

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

• 因为只有 lambda 表达式可以
有表达体,没有
匿名方法表达式可以是
成功转换为
表达式树类型(§4.6)。

我认为:

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

相当于:

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

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

如果有一个等价的 delegate{} ,它可能是:

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

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

To elaborate on tvanfosson's answer; this behavior is described in the C# 3.0 language specification (§7.14):

The behavior of lambda-expressions and
anonymous-method-expressions is the
same except for the following points:

• anonymous-method-expressions permit
the parameter list to be omitted
entirely, yielding convertibility to
delegate types of any list of value
parameters.

• lambda-expressions permit parameter
types to be omitted and inferred
whereas anonymous-method-expressions
require parameter types to be
explicitly stated.

• 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.

• Since only lambda-expressions can
have an expression body, no
anonymous-method-expression can be
successfully converted to an
expression tree type (§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.

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.

故人的歌 2024-07-19 07:37:15

正如其他人所说,不,您不能跳过将参数声明为 lambda。 但是,为了干净起见,我建议给它们起一个名称,例如 _。 例如,

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

您本身并没有忽略它们,而是表明您不关心它们是什么并且不会使用它们。

As others said, no, you can't skip declaring the parameters to a 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.

情场扛把子 2024-07-19 07:37:15

()=>; ... 语法明确指定 lambda 不带参数。 也许可以修改语言,以便 () =>; 真正的意思是“为我推断这个 lambda 的参数”,就像委托语法一样,但这会让语言变得更加复杂。 设计新的语言功能时,从负 100 开始,我认为这个没有通过测试。

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

The () => ... syntax explicitly specifies that the lambda takes no parameters. 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. 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).

卖梦商人 2024-07-19 07:37:15

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

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

I'd say it's to have a forced use of the parameters of the lambda expression.

Take your first example, how would you interact with the passed in value, there's no local representation of it.

你的笑 2024-07-19 07:37:15

那这个呢?

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

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;
}
漫漫岁月 2024-07-19 07:37:15

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

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

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

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

动作; 行动=_=> Console.WriteLine("lambda");

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

动作action = () => Console.WriteLine("lambda");

Actually, delegate {} does not specify any parameters and fits any delegate method signature - therefore it is permitted in your first construcion.

The Lambda expression () => ...; specifically states parameterless delegate, which contradicts the signature required by Action - a delegate with single parameter.

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 = () => Console.WriteLine("lambda");

∞觅青森が 2024-07-19 07:37:14

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

C# 匿名方法参考

有一种情况,
匿名方法提供
lambda 中未找到的功能
表达式。 匿名方法启用
您省略参数列表,并且
这意味着匿名方法
可以转换为代表
各种签名。 这不是
可以使用 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.... 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. Obviously the latter is not consistent with the defined Action so you get the error.

C# Anonymous Method Reference

There is one case in which an
anonymous method provides
functionality not found in lambda
expressions. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文