对“Action”委托和 lambda 表达式的混淆

发布于 2024-08-03 20:54:13 字数 927 浏览 4 评论 0原文

private void StringAction(string aString) // method to be called
{
    return;
}

private void TestDelegateStatement1() // doesn't work
{
    var stringAction = new System.Action(StringAction("a string"));
    // Error: "Method expected"
}

private void TestDelegateStatement2() // doesn't work
{
    var stringAction = new System.Action(param => StringAction("a string"));
    // Error: "System.Argument doesn't take 1 arguments"

    stringAction();
}

private void TestDelegateStatement3() // this is ok
{
    var stringAction = new System.Action(StringActionCaller);

    stringAction();
}

private void StringActionCaller()
{
    StringAction("a string");
}

我不明白为什么 TestDelegateStatement3 有效,但 TestDelegateStatement1 失败。在这两种情况下,Action 都提供了一个采用零参数的方法。他们可能调用一个采用单个参数(aString)的方法,但这应该是无关紧要的。他们不接受参数。这是不可能用 lamda 表达式来做的,还是我做错了什么?

private void StringAction(string aString) // method to be called
{
    return;
}

private void TestDelegateStatement1() // doesn't work
{
    var stringAction = new System.Action(StringAction("a string"));
    // Error: "Method expected"
}

private void TestDelegateStatement2() // doesn't work
{
    var stringAction = new System.Action(param => StringAction("a string"));
    // Error: "System.Argument doesn't take 1 arguments"

    stringAction();
}

private void TestDelegateStatement3() // this is ok
{
    var stringAction = new System.Action(StringActionCaller);

    stringAction();
}

private void StringActionCaller()
{
    StringAction("a string");
}

I don't understand why TestDelegateStatement3 works but TestDelegateStatement1 fails. In both cases, Action is supplied with a method that takes zero parameters. They may call a method that takes a single parameter (aString), but that should be irrelevant. They don't take a parameter. Is this just not possible to do with lamda expressions, or am I doing something wrong?

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

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

发布评论

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

评论(4

正如您所说,Action 不带任何参数。
如果这样做:

var stringAction = new System.Action(StringAction("a string"));

您实际上执行了此处的方法,因此这不是方法参数。

如果你这样做:

var stringAction = new System.Action(param => StringAction("a string"));

你告诉它你的方法需要一个名为 param 的参数,而 Action 则不需要。

因此,正确的方法是:

var stringAction = new System.Action( () => StringAction("a string"));

或更紧凑:

Action stringAction = () => StringAction("a string");

空括号用于指示 lambda 不带任何参数。

As you said, Action doesn't take any parameters.
If you do this:

var stringAction = new System.Action(StringAction("a string"));

You actually execute the method here, so that is not a method parameter.

if you do this:

var stringAction = new System.Action(param => StringAction("a string"));

you tell it that your method takes a parameter called param, which Action does not.

So the correct way to do this would be:

var stringAction = new System.Action( () => StringAction("a string"));

or more compact:

Action stringAction = () => StringAction("a string");

the empty brackets are used to indicate the lambda doesn't take any parameters.

再可℃爱ぅ一点好了 2024-08-10 20:54:13

Action 委托被定义为方法的委托,没有参数并且返回 void。在示例 1 中,您犯了 2 个错误:
1.您正在尝试提供需要参数的方法
2. 您正在调用该方法,并且没有将其作为参数提供(它应该是 new Action(methodName)),但它不会工作,因为 1.

在示例 2 中,您再次犯了同样的错误,您的lambda 接受一个参数,你应该这样写:
new Action(() => StringAction("a string"));

如果你想创建一个委托,它将接受一个参数,你应该这样做:
new Action(myStringParam => StringAction(myStringParam));

因此,在您的情况下,完整的代码将如下所示:


private void StringAction(string aString) // method to be called
{
    return;
}

private void TestDelegateStatement1() // now it works
{
    var stringAction = new Action<string>(StringAction);
    //You can call it now:
    stringAction("my string");
}

private void TestDelegateStatement2() // now it works
{
    var stringAction = () => StringAction("a string");
    //Or the same, with a param:
    var stringActionParam = (param) => StringAction(param);

    //You can now call both:
    stringAction();
    stringActionParam("my string");
}

private void TestDelegateStatement3() // this is ok
{
    var stringAction = new System.Action(StringActionCaller);

    stringAction();
}

private void StringActionCaller()
{
    StringAction("a string");
}

Action delegate is defined as delegate to method, that has no parameters and returns void. In sample 1, you are making 2 mistakes:
1. You are trying to give method, that takes parameter
2. You are invoking the method, and not giving it as a parameter (it should be new Action(methodName)), although, it wouldn't work because of 1.

In sample 2, you are making the same mistake again, your lambda is taking a parameter, you should write it like this:
new Action(() => StringAction("a string"));

If you want to create a delegate, that will take a parameter, you should do it like this:
new Action<string>(myStringParam => StringAction(myStringParam));

So, in your case, complete code would look like this:


private void StringAction(string aString) // method to be called
{
    return;
}

private void TestDelegateStatement1() // now it works
{
    var stringAction = new Action<string>(StringAction);
    //You can call it now:
    stringAction("my string");
}

private void TestDelegateStatement2() // now it works
{
    var stringAction = () => StringAction("a string");
    //Or the same, with a param:
    var stringActionParam = (param) => StringAction(param);

    //You can now call both:
    stringAction();
    stringActionParam("my string");
}

private void TestDelegateStatement3() // this is ok
{
    var stringAction = new System.Action(StringActionCaller);

    stringAction();
}

private void StringActionCaller()
{
    StringAction("a string");
}
深海里的那抹蓝 2024-08-10 20:54:13

我不是这方面的专家,但你尝试过吗?

public void TestDelegateStatement4
{
    var stringAction = () => StringAction("a string");
}

I'm not an expert on this, but have you tried this?

public void TestDelegateStatement4
{
    var stringAction = () => StringAction("a string");
}
挽手叙旧 2024-08-10 20:54:13

在 C# 2.0 中,Action 委托是一个不接受参数的 void 委托。
在更高版本中,有通用的 Action 委托,其中 T 指定参数类型。

这应该有效:

var stringAction = new Action<string>(param => StringAction(param));

或者更好:

var stringAction = new Action<string>(StringAction); // using method group conversion

然后,你可以打电话

stringAction("Hello world");

In C# 2.0, the Action delegate is a void delegate that doesn't accept parameters.
In later versions, there's the generic Action<T> delegate, where T specifies the parameter type.

This should work:

var stringAction = new Action<string>(param => StringAction(param));

or even better:

var stringAction = new Action<string>(StringAction); // using method group conversion

then, you can call

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