参数类型'System.Action'不能赋予参数类型'void'

时间:2010-08-02 12:36:22

标签: c# c#-3.0

这是我的测试代码:

class PassingInActionStatement
{
    static void Main(string[] args)
    {
        var dsufac = new DoSomethingUsefulForAChange();

        dsufac.Do(WriteToConsole);
        dsufac.Do2(s => WriteToConsoleWithSomethingExtra("Test"));
        dsufac.Do(WriteToConsoleWithSomethingExtra("Test")); // Does not compile
    }

    internal static void WriteToConsole()
    {
        Console.WriteLine("Done");
    }

    internal static void WriteToConsoleWithSomethingExtra(String input)
    {
        Console.WriteLine(input);
    }
}

internal class DoSomethingUsefulForAChange
{
    internal void Do(Action action)
    {
        action();
    }

    internal void Do2(Action<String> action)
    {
        action("");
    }
}

前2个电话有效,但我想知道为什么第3个电话没有。我不喜欢Do2中的代码,因为我在那里输入类型action("")似乎很奇怪,以便让它工作。

有人可以解释一下我不理解的两件事吗?

  1. 为什么我不能通过调用Do
  2. 来编写第三行
  3. 为什么我必须写动作(“”)才能让它在Do2中起作用

4 个答案:

答案 0 :(得分:34)

dsufac.Do(WriteToConsoleWithSomethingExtra("Test"));

实际上先调用函数(WriteToConsoleWithSomethingExtra("Test")),然后尝试将结果传递给Do。由于没有结果(void),因此无法实现。

你真正想要的是:

dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test"));

内部部分声明一个不带任何内容的函数(() =>位),在执行时调用WriteToConsoleWithSomethingExtra("Test")然后您的dsufac.Do电话会收到一个与预期相符的行动。

至于Do2 - 您已将其声明为Action<String>,这意味着action接受一个参数的函数。你必须传递一个字符串。该字符串可能为空,例如在您的action("")示例中,或者它可能在外部传递,如下所示:

dsufac.Do3(WriteToConsole, "Test");

...

internal void Do3(Action<String> action, String str)
{
    action(str);
}

答案 1 :(得分:3)

在您的代码中

dsufac.Do(WriteToConsoleWithSomethingExtra("Test"));

的解释如下

var variable = WriteToConsoleWithSomethingExtra("Test");
dsufac.Do(variable);

由于WriteToConsoleWithSomethingExtra(“Test”)的返回类型为void,因此您无法将其实际传递给dsufac.Do()。这就是它没有编译的原因。但是对于第一个

dsufac.Do(WriteToConsole);

您没有调用该函数,而是将其作为方法组传递,稍后在dsufac对象的Do()方法中调用该方法组。但是如果你想把第3行写成第1行,你可以使用

dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test"));

答案 2 :(得分:1)

  1. 请求Action(即不带参数且不返回任何值的方法)。因此WriteToConsoleWithSomethingExtra不合适 - 需要一个字符串参数。
  2. Do2接受Action<T>(即接受一个T参数并且不返回任何值的方法)。因此,当您调用委托/操作时,您需要提供一个类型为T的参数,此处为String。

答案 3 :(得分:1)

我在Silverlight应用程序中做了一段时间这样的事情。现在,当它运行时,其中一部分会中断 这发生在Silverlight子窗口中:

(my object context).SaveChanges(() => ChangesSaved());

private void ChagngesSaved()
{
   DialogResult = true: // is supposed to close the child window. line gets hit, does not close
}