спецификация языка С# описывает вывод типа в разделе §7.5.2. В нем есть детали, которые я не понимаю. Рассмотрим следующий случай:
// declaration
void Method<T>(T obj, Func<string, T> func);
// call
Method("obj", s => (object) s);
Компиляторы Microsoft и Mono С# правильно заключают T
= object
, но мое понимание алгоритма в спецификации даст T
= string
, а затем сбой. Вот как я это понимаю:
Первая фаза
-
Если Ei - анонимная функция, то вывод о явном типе параметров (§7.5.2.7) производится из Ei в Ti
⇒ не действует, потому что выражение лямбда не имеет явных типов параметров. Правильно?
-
В противном случае, если Ei имеет тип U, а xi - параметр значения, то вывод с нижней границей производится от U до Ti.
⇒ первый параметр имеет статический тип
string
, поэтому он добавляетstring
к нижним границам дляT
, правильно?
Вторая фаза
-
Все незафиксированные переменные типа Xi, не зависящие от (п. 7.5.5.5), фиксированы (X7.2.2.10).
⇒
T
нефиксирован;T
не зависит от чего-либо... так чтоT
должно быть исправлено, правильно?
§7.5.2.11 Фиксация
-
Набор типов кандидатов Uj начинается как набор всех типов в наборе оценок для Xi.
⇒ {
string
(нижняя граница)} -
Затем мы рассмотрим каждую оценку для Xi по очереди: [...] Для каждой нижней границы U множества Xi из набора кандидатов удаляются все типы Uj, к которым не существует неявного преобразования из U. [...]
⇒ не удаляет что-либо из набора кандидатов, верно?
-
Если среди остальных типов кандидатов Uj существует уникальный тип V, из которого происходит неявное преобразование ко всем другим типам кандидатов, тогда Xi фиксируется на V.
⇒ Поскольку существует только один тип кандидата, это пустое значение, поэтому Xi фиксируется на
string
. Правильно?
Итак, где я ошибаюсь?