无法将“void”转换为“System.Action”。

23
将带参数的方法传递给接受Action类型参数的方法会导致语法错误:

无法将“void”转换为“System.Action”

但是,如果我传递一个没有任何参数的方法,它就可以正常工作。

我假设在传递没有参数的方法时,C#会自动执行某些操作。

我想知道它在幕后正在做什么以及如何处理具有参数的方法。

public void Invoke(Action action){ /*Code Here */ }

public void Method1(){ /*Code Here */}

public void Method2(int param){ /*Code Here */ }

public void test()
{
    int testParam = 1;
    //** This works
    Invoke(Method1);
    //** This does not work
    Invoke(Method2(testParam));     
}

13
调用(() => Method2(testParam)) 方法。 - DavidG
@TheColonel26 你收到了完全相同的错误信息,遇到了完全相同的问题,并且有了完全相同的解决方案。这是一个完全的重复。你读了答案吗?将该答案应用于你的问题后,为什么无法解决你的问题? - Servy
@Servy: 我确实阅读了它,这是同样的问题,但错误消息措辞不同。“无法从'void'转换为'System.Action'”不等于“参数类型'void'不可分配到参数类型'System.Action'”,这就是为什么我没有发现它的原因。 - TheColonel26
1
@TheColonel26 这很奇怪,因为我字面上复制粘贴了你问题的标题到谷歌,那就是最顶部的结果。这就是我找到覆盖你确切情况的完全重复问题的方式。你略微改变了问题的措辞,并没有阻碍你找到重复问题,也不会改变它是完全相同的问题和解决方案的事实。 - Servy
我在之前编译通过的代码上遇到了相同的错误(无法将“void”转换为“System.Action”)。显示错误的代码行与之前正常工作的完全相同。有人遇到过类似的情况吗? - Paul McCarthy
显示剩余2条评论
2个回答

43

你的Invoke方法期望一个Action,但是你试图向它传递一个方法的返回值,而在这种情况下该方法的返回值是void。相反,你可以使用lambda来创建Action

Invoke(() => Method2(testParam));

更明确地说:

Action a = () => Method2(testParam);
Invoke(a);
第一个版本对您有效的原因是传递没有括号的方法是上述代码的简写,因此这些是等效的。
Invoke(Method1);
Invoke(() => Method1());

为什么调用Invoke(Method1)可以工作呢?编译器为什么假定我想要发送一个Action给Invoke而不是方法的返回类型? - TheColonel26
我会在我的回答中添加这个。 - DavidG
1
@TheColonel26 因为在这种情况下,你没有在方法名后加上 () ,所以实际上你并没有调用该方法。你正在传递该方法的名称,C# 将其解释为你想将其转换为委托。 - juharr

6
你的代码不能正常工作,因为Method2(testParam)执行了该方法,而不是提供了一个可以在将来任何时候执行的动作。
你需要使用lambda表达式:
Invoke(() => Method2(testParam));

另一段代码 (Invoke(Method1)) 能够工作,是因为您在此处提供了一个委托给该方法(请注意括号的缺失:没有执行,只是对该方法的引用)。 委托可以转换为操作。

我也是。谢谢 @DavidG - Patrick Hofman
旁注:最近的负面评价使得 Stack 变得难以参与。我的原始评论:你不需要为之前的调用 Invoke(Method1); 制作相同的 lambda 吗?Method1 不是在 Invoke 的主体被调用之前执行吗? - tatmanblue
@tatmanblue 不是,它是一个委托。 - Patrick Hofman
@PatrickHofman 谢谢。 - tatmanblue
@tatmanblue 关于你的第一句话,不,它并不是。除了像这个例子中的 DV 之类的一些例外,好质量的内容通常会得到赞同。 - DavidG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接