I've been playing a little with generics and delegates and I have found something I don't understand. I have quite similar generic static methods, one accepts Action<T>
and the second one accepts Func<T>
. Now the problem: if I call the one accepting Func<T>
without explicit Type, compiler is fine with that. But with the one accepting Action<T>
my program can't be compiled (see the code for error message).
My question is: Why is compiler able to recognize return type, but is not able to recognize argument type?
public interface IMessage
{ }
public class Message : IMessage
{
}
static void HandleAction<TMessage>(Action<TMessage> action)
where TMessage : IMessage
{ }
static void HandleFunction<TMessage>(Func<TMessage> action)
where TMessage : IMessage
{ }
static void A(Message message)
{ }
static Message F()
{
return new Message();
}
static void Main(string[] args)
{
// this one is ok
HandleFunction(F);
// compiler error:
// The type arguments for method
// 'template_test.Program.HandleAction<TMessage>(System.Action<TMessage>)'
// cannot be inferred from the usage.
//Try specifying the type arguments explicitly.
//HandleAction(A);
// this one is ok
HandleAction<Message>(A);
}
I'm using .NET 4.5 in Visual Studio 2012.
Methods can be overloaded by their arguments and all overloads form one method group, so for example
void Xyz(int i)
andvoid Xyz(string s)
are within same method group calledXyz
. Compiler is not able to deduct a type of argument even if user defines only one method, because behaviour of compiler is quite strict.Methods can't be overloaded by return types, so you can't have
int Xyz()
andstring Xyz()
within same class. Return type can be deducted by compiler easily, because there is no overloading.It was not obvious for me for the first time, but it has been quite clear after I realized that I could create an overload.