I am wondering why the C# 3.0 compiler is unable to infer the type of a method when it is passed as a parameter to a generic function when it can implicitly create a delegate for the same method.
Here is an example:
class Test { static void foo(int x) { } static void bar<T>(Action<T> f) { } static void test() { Action<int> f = foo; // I can do this bar(f); // and then do this bar(foo); // but this does not work } }
I would have thought that I would be able to pass foo
to bar
and have the compiler infer the type of Action<T>
from the signature of the function being passed but this does not work. However I can create an Action<int>
from foo
without casting so is there a legitimate reason that the compiler could not also do the same thing via type inference?
Maybe this will make it clearer:
public class SomeClass { static void foo(int x) { } static void foo(string s) { } static void bar<T>(Action<T> f){} static void barz(Action<int> f) { } static void test() { Action<int> f = foo; bar(f); barz(foo); bar(foo); //these help the compiler to know which types to use bar<int>(foo); bar( (int i) => foo(i)); } }
foo is not an action - foo is a method group.
Edit: I've added two (more) ways to help the compiler figure out the type (ie - how to skip the inference steps).
From my reading of the article in JSkeet's answer, the decision to not infer the type seems to be based on a mutual infering scenario, such as
static void foo<T>(T x) { } static void bar<T>(Action<T> f) { } static void test() { bar(foo); //wut's T? }
Since the general problem was unsolve-able, they choose to left specific problems where a solution exists as unsolved.
As a consequence of this decision, you won't be adding a overload for a method and getting a whole lot of type confusion from all the callers that are used to a single member method group. I guess that's a good thing.
The reasoning is that if the type ever expands there should be no possibility of failure. i.e., if a method foo(string) is added to the type, it should never matter to existing code - as long as the contents of existing methods don't change.
For that reason, even when there is only one method foo, a reference to foo (known as a method group) cannot be cast to a non-type-specific delegate, such as Action<T>
but only to a type-specific delegate such as Action<int>
.
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