I have been trying to figure this out and it's really bugging me. I have some code that looks like this
static T MyFunction<T>(Func<T> action, int i, int i2)
{
...some code here
}
When I need to call this code I tried this
var result = MyFunction<List<string>>(MethodThatReturnsListofString(int number), 1,2)
It fails stating that the best overload has invalid arguments
But when I tried the following
var result = MyFunction<List<string>>(() => MethodThatReturnsListofString(int number), 1,2)
It works fine. What is the function of "() =>" in this case. I thought() could not be used with methods required more than 0 args.
MyFunction<T>
expects as first parameter a method that takes no arguments and returns the type T
.
In your first attempt, you call MethodThatReturnsListofString(number)
and try to provide the result (a List<T>
) as parameter instead of a method.
In your second try, you create a method with the required signature by typing () => MethodThatReturnsListofString(number)
and provide this as parameter.
To make it more clear, you could have created a method like
static List<T> MyAnonymousMethod()
{
return MethodThatReturnsListofString(number);
}
and then called
MyFunction<List<string>>(MyAnonymousMethod, 1, 2);
With () => MethodThatReturnsListofString
you declare an anonymous method inline and so you don't need to create MyAnonymousMethod
first. This part of your code is what is called a lambda expression.
Note that by declaring this lambda, MethodThatReturnsListofString
is not executed immediatly! It will be executed only when MyFunction
really calls this action parameter like
static T MyFunction<T>(Func<T> action, int i, int i2)
{
// ... some code
var result = action();
// ... more code
}
You're passing a lambda that takes no arguments.
That is the correct syntax to write such a lambda.
The fact that your lambda happens to call a function that takes arguments is completely irrelevant.
This simply means that you are invoking an anonymous method which accepts 0 arguments.
If its () => a+b
it returns the addition
else if you provide it a body
like ()=> { } its upto you to return or not
also if you provide the delegate which needs it to return then you have to return. for eg Action doesnt require but Func do require
MethodThatReturnsListofString(number)
is not a Func<T>
. It is a Func<T, U>
, where List<string>
is one type argument and int
is the other. Moreover, you are providing the result of this method — not the method itself — as the argument to your function.
On the other hand, this expression is a Func<T>
:
() => MethodThatReturnsListofString(number)
This is a lambda expression that creates a delegate with no input parameters and one output parameter (the List<string>
). The number
variable passed to MethodThatReturnsListofString()
is not part of the function definition. The code works because the number
variable is instead a closure. The variable is captured by the compiler and used by the method, but it's not part of the method signature.
I thought ()
could not be used with methods required more than 0 args.
That is correct. But remember that the Func<T>
type used for your action
argument here defines a function that accepts 0 arguments and returns one value. So what you are doing is matching your expression to the Func<T>
type of MyFunction
's action
parameter. Just because you then call a method that requires an argument within your new Func<T>
delegate doesn't mean the delegate itself requires an argument.