混淆`Action`委托和lambda表达式(Confusion over `Action` del

2019-07-04 23:50发布

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表达式,还是我做错了什么?

Answer 1:

正如你所说,行动不带任何参数。 如果你这样做:

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

实际上,你在这里执行方法,所以这不是一个方法参数。

如果你这样做:

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

你告诉它,你的方法接受一个名为参数param ,其操作不会。

因此,要做到这一点,正确的方法是:

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

或更紧凑:

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

空括号用来指示拉姆达不带任何参数。



Answer 2:

Action委托被定义为代表到的方法,即没有参数和返回void。 在样品1,你这是2级的错误:
1.您正在试图给方法,即采用参数
2.要调用的方法,而不是给它作为一个参数(它应该是新的行动(方式)),但是,它不会因为1工作。

在样品2中,你再次犯同样的错误,你的拉姆达进行参数,你应该把它写这样的:
new Action(() => StringAction("a string"));

如果你想创建一个代表,这将需要一个参数,你应该这样做是这样的:
new Action<string>(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");
}


Answer 3:

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

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


Answer 4:

在C#2.0中, Action委托是一种void委托,它不接受参数。 在以后的版本,有通用的Action<T>委托,其中T指定参数类型。

这应该工作:

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

甚至更好:

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

然后,你可以调用

stringAction("Hello world");


文章来源: Confusion over `Action` delegate and lambda expressions