Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argument type 'void' is not assignable to parameter type 'System.Action'

Tags:

c#

c#-3.0

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 that 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?

  1. Why I can not write the third line like that with calling Do
  2. Why I have to write action("") in order get it to work in Do2
like image 691
Nyla Pareska Avatar asked Aug 02 '10 12:08

Nyla Pareska


People also ask

Is not assignable to parameter of type void?

The error "Argument of type 'void' is not assignable to parameter of type" occurs when we forget to return from a function and pass a void argument to the calling function. To solve the error, make sure you return a value of the expected type, before passing it to the caller.

Is not assignable to parameter of type?

The error "Argument of type string | undefined is not assignable to parameter of type string" occurs when a possibly undefined value is passed to a function that expects a string . To solve the error, use a type guard to verify the value is a string before passing it to the function.


2 Answers

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"));
like image 31
Anindya Chatterjee Avatar answered Sep 26 '22 14:09

Anindya Chatterjee


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);
}
like image 199
Roman Starkov Avatar answered Sep 23 '22 14:09

Roman Starkov