I'm trying to write a function that takes a function as one of its arguments -- a task I've done many times before. This works fine:
int RunFunction(Func<int,int> f, int input) {
return f(input);
}
int Double(int x) {
return x*2;
}
// somewhere else in code
RunFunction(Double,5);
Yet this doesn't work:
public static class FunctionyStuff {
public static int RunFunction(this Func<int,int> f, int input) {
return f(input);
}
}
// somewhere else in code
Double.RunFunction(5);
Any idea why the first one works and the second one doesn't?
The first version is performing a method group conversion as part of the "argument to parameter" matching. This conversion doesn't happen for extension methods. The same is true for lambda expressions - you couldn't write:
((int x) = > x * 2).RunFunction(10);
either.
Section 7.6.5.2 of the C# 4 spec gives details of extension method invocations. It starts off by requiring that the method invocation is of one these forms:
expr.identifier ( )
expr.identifier ( args )
expr.identifier < typeargs > ( )
expr.identifier < typeargs > ( args )
The type of the expression (expr
) is then used in this rule:
An extension method Ci.Mj is eligible if
- [...]
- An implicit identity, reference, or boxing conversion exists from expr to the type of the first parameter of Mj.
The annotated version of the spec then includes this comment from Eric Lippert:
This rule ensures that making a method that extends
double
does not also extendint
. It also ensures that no extension methods are defined on anonymous functions or method groups.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With