我已經進行了如下推理測試:爲什麼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'成功不同。 –