无法推断来自Action <t>的类型参数,但是从Func <t>可以</t> </t>

时间:2014-03-26 18:28:57

标签: c# generics delegates

我一直在玩仿制药和代表,我找到了一些我不理解的东西。我有非常相似的通用静态方法,一个接受Action<T>,第二个接受Func<T>。现在问题是:如果我在没有显式类型的情况下调用接受Func<T>的那个,编译器就可以了。但是如果接受Action<T>我的程序无法编译(请参阅错误消息代码)。

我的问题是:为什么编译器能够识别返回类型,但是无法识别参数类型?

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);
}

我在Visual Studio 2012中使用.NET 4.5。

1 个答案:

答案 0 :(得分:8)

方法可以通过参数重载,所有重载形成一个方法组,因此例如void Xyz(int i)void Xyz(string s)位于名为Xyz的同一方法组中。即使用户只定义了一个方法,编译器也无法扣除一种参数,因为编译器的行为非常严格。

返回类型不能重载方法,因此您不能在同一个类中拥有int Xyz()string Xyz()。返回类型可以很容易地被编译器扣除,因为没有重载。

这对我来说并不是第一次,但在我意识到我可以创造一个过载之后就已经很清楚了。