This is my test code:
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("");
}
}
The first 2 calls work but I am wondering why the 3rd one does not. I do not fancy the code inside Do2 as it seems strange tha开发者_高级运维t I have type type action("")
in there in order to get it to work.
Could someone please explain the 2 things I do not understand please?
- Why I can not write the third line like that with calling Do
- Why I have to write action("") in order get it to work in Do2
dsufac.Do(WriteToConsoleWithSomethingExtra("Test"));
actually calls the function first (WriteToConsoleWithSomethingExtra("Test")
) and then attempts to pass the result into Do
. Since there is no result (void
), it's not possible.
What you actually want is this:
dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test"));
The inner part declares a function that takes nothing (the () =>
bit), which calls WriteToConsoleWithSomethingExtra("Test")
when executed. Then your dsufac.Do
call will receive an action, like it expects.
As for Do2
- you've declared it as taking Action<String>
, which means that action
is a function that takes one argument. You have to pass it a string. That string might be empty, like in your action("")
example, or it might be passed in externally, as in something like this:
dsufac.Do3(WriteToConsole, "Test");
...
internal void Do3(Action<String> action, String str)
{
action(str);
}
In your code
dsufac.Do(WriteToConsoleWithSomethingExtra("Test"));
is interpreted like the following
var variable = WriteToConsoleWithSomethingExtra("Test");
dsufac.Do(variable);
As the return type of WriteToConsoleWithSomethingExtra("Test") is void, so you can not actually pass it to dsufac.Do(). That is why its not getting compiled. But for the first one
dsufac.Do(WriteToConsole);
you are not calling the function, rather you are passing it as a method group, which is later get invoked in the Do() method of dsufac object. But if you want to write the 3rd line as the 1st one, you can use
dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test"));
- Do expects an
Action
(i.e. method which take no parameters and returns no value). HenceWriteToConsoleWithSomethingExtra
is not a valid fit - takes one string parameter. - Do2 accepts an
Action<T>
(i.e. method which takes in one T parameter and returns no value). Hence when you invoke the delegate/action you need to supply one parameter of type T, here String.
精彩评论