我已经进行了如下推理测试:为什么C#无法从非泛型静态方法的签名推断泛型类型参数类型?
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
}
}
结果似乎表明,C#编译器无法推断通用类型参数从非泛型方法组委托函数的参数。
我什么困扰最深的是,C#是可以推断Func<T1, T2>
从方法的返回值类型变量在ConsumeFunc1Func2
,但无法推断类型Func<T, T>
在ConsumeFunc2c
。
这个问题类似于T of Func<S, T> is inferred from output of lambda expression only when S and T are different?的问题,但不是具有未知参数类型的lambdas,我们有非泛型方法组。
Why can't C# infer type from this seemingly simple, obvious case问题的答案类型的问题“为什么非模糊的非泛型方法不足以进行推理?”和“为什么参数类型和推理的返回值类型之间存在差异?”。
问题:
为什么C#编译器推断Func<T>
使用的返回值的类型的类型,但没有看到Func<T, T>
情况下成功?
为什么C#编译器推断从Func<T1>
为Func<T1, T2>
的T1
类型参数在ConsumeFunc1Func2
,但不能推断ConsumeFunc2c
为Func<T, T>
从自身T
型参数,它似乎是更容易?
在ConsumeFunc1Func2中,编译仍然只从返回值推断,而不是参数类型。 T1从GiveInt的返回值中解析出来,T2从TakeAndGiveInt的返回值中解析出来。因此,ConsumeFunc1Func2案例没有增加额外的秘密。 – Baldrick
我会很好的阅读C#4.0规范的第7.5.2节。它非常易读,描述了类型推断的各个阶段,以及它们与方法组的关系。 – Baldrick
'ConsumeFunc2b'表明''Func , T>'返回类型'T'可以从'TakeAndGiveInt'解析。但是当'?'也是'T'时,'ConsumeFunc2c'中的'Func'就是这种情况,编译器似乎忘记了参数'T'与已经推断的'T'相同。与'ConsumeFunc1Func2'成功不同。 –