Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

type argument from Action<T> cannot be inferred, but from Func<T> can be

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.

like image 222
Stan Prokop Avatar asked Mar 26 '14 18:03

Stan Prokop


1 Answers

Methods can be overloaded by their arguments and all overloads form one method group, so for example void Xyz(int i) and void Xyz(string s) are within same method group called Xyz. 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() and string 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.

like image 140
Stan Prokop Avatar answered Oct 01 '22 04:10

Stan Prokop