这是我的测试代码:
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("")
似乎很奇怪,以便让它工作。
有人可以解释一下我不理解的两件事吗?
答案 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)
Action
(即不带参数且不返回任何值的方法)。因此WriteToConsoleWithSomethingExtra
不合适 - 需要一个字符串参数。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
}