Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type inference discrepancy between method and extension method arguments

Let's say I have the following method defined:

int ReturnNumber(int number)
{
    return number;
}

Now, let's say that I also have the following two methods defined; a regular method:

void Print(Func<int, int> function)

and an extension method:

static void Print(this Func<int, int> function)

I can call the former like this:

Print(ReturnNumber); // Regular method call, seems to implicitly convert ReturnNumber to Func<int, int>

but I can't do that with the latter:

ReturnNumber.Print(); // Extension method call, does not seem to do the implicit conversion -- results in compiler error

though I can do this:

((Func<int, int>)ReturnNumber).Print(); // I perform the conversion explicitly

I'm assuming that there's some "magic" that happens when you pass a method as an argument to another method, and that the compiler is therefore able to guess that it should try to convert the ReturnNumber to Func<int, int>, whereas the compiler doesn't do any such thing for extension methods. Is this correct? My question can be summarized as: why can't you call an extension method on a method, whereas you can call an extension method on a delegate instance? Does it have something to do with the fact that the compiler doesn't treat methods as objects, but only treats delegates as objects?

like image 273
Brian Snow Avatar asked Oct 22 '15 17:10

Brian Snow


1 Answers

That method group can be implicitly converted to Func<int, int>, which means if you're using that method group in a location where a Func<int, int> is expected (such as by passing it to a method who's parameter is Func<int, int> then it's able to convert it into such a delegate.

But until you've actually converted that method group into a Func<int, int> you can't call any instance methods on it, as it has none. When you explicitly cast it to a Func<int, int> then you're changing that expression from a method group (which isn't itself a Func<int, int>) into a Func<int, int>.

like image 166
Servy Avatar answered Oct 12 '22 22:10

Servy