Считайте следующее объявление универсального служебного класса в Delphi 2010:
TEnumerableUtils = class
public
class function InferenceTest<T>(Param: T): T;
class function Count<T>(Enumerable: TEnumerable<T>): Integer; overload;
class function Count<T>(Enumerable: TEnumerable<T>; Filter: TPredicate<T>): Integer; overload;
end;
Так или иначе вывод типа компилятора, кажется, имеет проблемы здесь:
var
I: Integer;
L: TList<Integer>;
begin
TEnumerableUtils.InferenceTest(I); // no problem here
TEnumerableUtils.Count(L); // does not compile: E2250 There is no overloaded version of 'Count' that can be called with these arguments
TEnumerableUtils.Count<Integer>(L); // compiles fine
end;
Первые работы вызова как ожидалось и T правильно выведены как Целое число.
Второй вызов не работает, если я также не добавляю <Integer
> - затем это работает, как видно в третьем вызове. Я делаю что-то не так или являюсь выводом типа в Delphi, просто не поддерживающем это (я не думаю, что это - проблема в Java, который является почему ожидается он для работы в Delphi, также).
Компилятору потребуется выполнить сопоставление с образцом, чтобы определить типы параметров; в настоящее время этого не происходит. Компилятор ограничен довольно простым выводом - если тип параметра относится к типу параметра типа, компилятор может это выяснить, но не более того.
Тип аргумента в вашем примере не является параметром простого типа, а представляет собой сконструированный универсальный тип (он создается с помощью параметра типа метода T, но, тем не менее, создается). Компилятору необходимо сделать два вывода, чтобы узнать значение T. Во-первых, он должен увидеть, что универсальный тип сконструированного типа является предком универсального типа TList
; и ему также необходимо сопоставить параметр типа T в списке параметров типа сконструированного типа с конкретным типом Integer в предке TList
.