我一直在与泛型和委托(delegate)打交道,发现一些我不理解的东西。我有非常相似的通用静态方法,一种接受Action<T>,第二种接受Func<T>。现在的问题是:如果我调用一个没有显式Type的接受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。

最佳答案

方法可以由其参数重载,并且所有重载都组成一个方法组,因此void Xyz(int i)void Xyz(string s)例如在同一方法组Xyz中。即使用户仅定义一个方法,编译器也无法推导一种类型的参数,因为编译器的行为非常严格。

返回类型不能重载方法,因此同一类中不能包含int Xyz()string Xyz()。返回类型可以很容易地被编译器推断出来,因为没有重载。

第一次对我来说并不明显,但是当我意识到自己可能会造成重载之后,这一点已经很清楚了。

关于c# - 不能推断出Action <T>的type参数,但是可以从Func <T>得出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41446498/

10-13 06:57
查看更多