Search code examples
c#lambdataskanonymous-methods

Lambda expression gives error while sending parameters while creating a new Task


I wrote the following code:

int n1 = 5
Task<int> myTask = new Task<int>(n1 => lib.MultiplyNumberTimes2(n1));
myTask.Wait();
Console.WriteLine("Result is " + myTask.Result.ToString());

Code explanation on what I want it to do:

I was expecting this to create a new task called myTask, which would accept a n1 int variable, and with it, it would run the lib.MultipleNumerTimes2 method. Then after waiting for it to complete, I would print the task result on screen with a myTask.Result statement.

But Visual studio shows an error on line 2 of my above code, underlining the n1 before the goto operator (=>) saying:

A local variable named 'n1' cannot be declared in this context, because it would give a different meaning to 'n1' which is already used in a 'parent or current' scope to denote something else

I'm guessing this a mistake in my lambda expression sintax which I can't yet understand. Aren't lambda expressions declared like: parameters => expression ? I know I'm declaring an anonymous expression, which I wan't to give an int variable, and then through the => operator use that same variable to run a function, but Visual Studio thinks I'm trying to declare a new n1 variable when in reality I just want to use it as a parameter. Also, while messing with the code I noticed changing line 2 for this fixes it:

Task<int> myTask = new Task<int>(() => lib.MultiplyNumerTimes2(n1));

I know I can leave it like that, but I would like to know what's wrong with my lambda expression that it won't let me send it any aprameters


Solution

  • The compilation error says exactly what you're doing wrong - you're trying to use the name n1 for two different things. You've got a local variable here:

    int n1 = 5;
    

    ... and then you're also trying to use it your lambda expression parameter name. You need to use a different parameter name... or just use your current approach which captures n1 and doesn't have any parameters.

    Note that there aren't any overloads of the Task<TResult> constructor which accept an Func<T, TResult>, so even just changing the name won't work:

    new Task<int>(foo => lib.MultiplyNumerTimes2(foo));
    

    But this would, as it calls the method accepting a Func<Object, TResult> and then provides the relevant value for the parameter.

    new Task<int>(foo => lib.MultiplyNumerTimes2((int) foo), n1);
    

    Note the cast, as the type of foo will just be object.