я провел следующие тесты логического вывода:Почему 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# компилятор может вывести T1
аргумент типа для Func<T1, T2>
из Func<T1>
в ConsumeFunc1Func2
, но не может вывести T
аргумент типа для Func<T, T>
от себя в ConsumeFunc2c
, который, кажется, проще?
В ConsumeFunc1Func2 компиляция по-прежнему выводит только из возвращаемого значения, а не типов параметров. T1 разрешен из возвращаемого значения GiveInt, а T2 разрешен из возвращаемого значения TakeAndGiveInt. Таким образом, никакая дополнительная тайна, добавленная случаем ConsumeFunc1Func2. – Baldrick
Я бы неплохо прочитал раздел 7.5.2 спецификации C# 4.0. Это вполне читаемо и описывает различные этапы вывода типа и как они относятся к группам методов. – Baldrick
'ConsumeFunc2b' показывает, что для' Func , T> 'тип возврата' T' может быть разрешен из 'TakeAndGiveInt'. Но когда '?' Также является 'T', как в случае с' Func 'в' ConsumeFunc2c', компилятор, похоже, забыл, что параметр 'T' совпадает с уже выведенным' T '. В отличие от успеха ConsumeFunc1Func2. –