Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function of a function works one direction, not the other

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?

like image 852
Joe Avatar asked Mar 18 '12 00:03

Joe


1 Answers

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 extend int. It also ensures that no extension methods are defined on anonymous functions or method groups.

like image 98
Jon Skeet Avatar answered Oct 18 '22 02:10

Jon Skeet