C# 对'Action'委托和lambda表达式的混淆

C# 对'Action'委托和lambda表达式的混淆,c#,delegates,lambda,C#,Delegates,Lambda,我不明白为什么TestDelegateStatement3可以工作,但是testdelegatestatement 1失败了。在这两种情况下,Action都提供了一个采用零参数的方法。他们可以调用一个采用单个参数(aString)的方法,但这应该是无关的。它们不接受参数。这是lamda表达式不可能实现的,还是我做错了什么?在C#2.0中,操作委托是一个不接受参数的无效委托。 在以后的版本中,有一个通用的操作委托,其中T指定参数类型 这应该起作用: private void StringActio

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

在C#2.0中,
操作
委托是一个不接受参数的
无效
委托。 在以后的版本中,有一个通用的
操作
委托,其中T指定参数类型

这应该起作用:

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

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

stringAction("Hello world");

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

public void TestDelegateStatement4
{
    var stringAction = () => StringAction("a string");
}
var stringAction = new System.Action(StringAction("a string"));
实际上,您在这里执行该方法,因此它不是一个方法参数

如果您这样做:

public void TestDelegateStatement4
{
    var stringAction = () => StringAction("a string");
}
var stringAction = new System.Action(StringAction("a string"));
您告诉它您的方法采用了一个名为
param
的参数,而该操作不采用该参数

因此,正确的方法是:

var stringAction = new System.Action(param => StringAction("a string"));
或更紧凑:

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

空括号用于表示lambda不接受任何参数。

操作
委托被定义为委托给方法,它没有参数并返回void。在示例1中,您犯了两个错误:
1.您试图给出一个方法,该方法采用参数
2.您正在调用该方法,但没有将其作为参数提供(它应该是new Action(methodName)),尽管由于1的原因,它无法工作

在示例2中,您又犯了同样的错误,您的lambda接受了一个参数,您应该这样写:
newaction(()=>StringAction(“字符串”))

如果要创建一个将接受一个参数的委托,应该这样做:
newaction(myStringParam=>StringAction(myStringParam))

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

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

private void StringAction(string aString)//要调用的方法
{
返回;
}
private void TestDelegateStatement1()//现在可以工作了
{
var stringAction=新操作(stringAction);
//您现在可以称之为:
stringAction(“我的字符串”);
}
private void TestDelegateStatement2()//现在可以工作了
{
var stringAction=()=>stringAction(“字符串”);
//或相同,带有参数:
变量stringActionParam=(param)=>StringAction(param);
//您现在可以同时调用这两个:
stringAction();
stringActionParam(“我的字符串”);
}
private void TestDelegateStatement3()//这没问题
{
var stringAction=new System.Action(StringActionCaller);
stringAction();
}
私有void StringActionCaller()
{
StringAction(“字符串”);
}

@Botz:对您的“更紧凑”语句的轻微更正:
System.Action stringAction=()=>stringAction(“字符串”)(编译器没有足够的信息知道
var
是一个
System.Action
)。

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