简体   繁体   English

为什么C#无法从非泛型静态方法的签名推断泛型类型参数类型?

[英]Why is C# unable to infer the generic type argument type form a non-generic static method's signature?

I have conducted the following inference tests: 我进行了以下推理测试:

static class InferenceTest {
    static void TakeInt(int a) { }
    static int GiveInt() { return 0; }
    static int TakeAndGiveInt(int a) { return 0; }

    static void ConsumeAction1<T>(Action<T> a) { }
    static void ConsumeFunc1<T>(Func<T> f) { }
    static void ConsumeFunc2a<T1, T2>(Func<T1, T2> f) { }
    static void ConsumeFunc2b<T>(Func<int, T> f) { }
    static void ConsumeFunc2c<T>(Func<T, T> f) { }
    static void ConsumeFunc1Func2<T1, T2>(Func<T1> f1, Func<T1, T2> f2) { }

    static void Main() {
        ConsumeAction1(TakeInt);        //error
        ConsumeFunc1(GiveInt);          //ok
        ConsumeFunc2a(TakeAndGiveInt);  //error
        ConsumeFunc2b(TakeAndGiveInt);  //ok
        ConsumeFunc2c(TakeAndGiveInt);  //error
        ConsumeFunc1Func2(GiveInt, TakeAndGiveInt); //ok
    }
}

The results seem to suggest that C# compiler is unable to infer the generic type arguments for the delegate function parameters from a non-generic method group. 结果似乎表明C#编译器无法从非泛型方法组推断委托函数参数的泛型类型参数。

What puzzles me the most is that C# is can infer the type arguments for Func<T1, T2> from the method return values in ConsumeFunc1Func2 , but is unable to infer the types for Func<T, T> in ConsumeFunc2c . 最让我困惑的是,C#可以从ConsumeFunc1Func2的方法返回值推断Func<T1, T2>的类型参数,但无法推断ConsumeFunc1Func2Func<T, T>ConsumeFunc2c

This question is similar to the T of Func<S, T> is inferred from output of lambda expression only when S and T are different? 这个问题类似于F的函数<S,T>只有当S和T不同时才从lambda表达式的输出中推断出来? question, but instead of lambdas with unknown parameter types we have non-generic method groups. 问题,但我们有非通用的方法组,而不是具有未知参数类型的lambda。

The Why can't C# infer type from this seemingly simple, obvious case question sort of answers the questions "Why are non-ambiguous non-generic methods not enough for inference?" 为什么不能从这个看似简单,明显的案例问题推断C#类型的问题,回答问题“为什么非模糊的非泛型方法不足以推理?” and "Why is there a difference between the argument types and the return value type for inference?". 和“为什么参数类型和推理的返回值类型之间存在差异?”。

Questions: 问题:

Why can the C# compiler infer the type of Func<T> using the type of the return value, but fails to see the success in the Func<T, T> case? 为什么C#编译器可以使用返回值的类型推断出Func<T>的类型,但是在Func<T, T>情况下无法看到成功?

Why can the C# compiler infer the T1 type argument for Func<T1, T2> from the Func<T1> in ConsumeFunc1Func2 , but cannot infer the T type argument for Func<T, T> from itself in ConsumeFunc2c which seems to be easier? C#编译器为什么可以推断出T1为类型参数Func<T1, T2>Func<T1>ConsumeFunc1Func2 ,但不能推断T为类型参数Func<T, T>从本身在ConsumeFunc2c这似乎是更容易?

Method parameters are not inspected. 不检查方法参数。

As suggested, in ConsumeFunc1Func2 the compiler is inferring only from return values. 如建议的那样,在ConsumeFunc1Func2中,编译器仅从返回值推断。 In ConsumeFunc2c, TakeAndGiveInt signature is not inspected to see if its method parameter type is actually of the same type of the method return type cause... method parameters are not inspected! 在ConsumeFunc2c中,未检查TakeAndGiveInt签名以查看其方法参数类型是否实际上与方法返回类型相同的类型原因...未检查方法参数!

In general, a method name will not uniquely identify a unique type Action<T> to which the method group could be assigned. 通常,方法名称不会唯一标识可以为其分配方法组的唯一类型Action<T> For example, even if there's only one overload of Fred and it takes a single Cat argument, that overload could be assigned not just to an Action<Cat> , but also to some other types like Action<Mammal> , Action<Animal> , or Action<Object> . 例如,即使只有一个Fred重载并且只需要一个Cat参数,该重载不仅可以分配给Action<Cat> ,还可以分配给其他类型,如Action<Mammal>Action<Animal> ,或Action<Object> While there are some cases where one type substitution would be in every way superior to any alternative, that is not always the case. 虽然在某些情况下,一种类型的替代在各方面都优于任何替代方案,但情况并非总是如此。 It's cleaner to define the language to require that the type of delegate be specified, than to have the compiler try to "guess", especially since having the compiler guess would mean that many things which shouldn't be breaking changes, would be (eg adding a method overload may render ambiguous a type inference which used to work). 定义语言要求指定委托类型比让编译器试图“猜测”更清晰,特别是因为编译器猜测会意味着许多不应该破坏变化的东西(例如添加方法重载可能会导致模糊的类型推断(以前的工作)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM