在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。
第二次通话不起作用,除非我还添加<Integer
&gt; - 然后它可以工作,如第三次调用中所见。我做错了什么或Delphi中的类型推断只是不支持这个(我不认为它是Java中的一个问题,这也是为什么它也可以在Delphi中工作)。
答案 0 :(得分:9)
编译器需要进行模式匹配以推断参数类型;它目前没有。编译器仅限于非常简单的推理 - 如果参数类型是类型参数类型,那么编译器可以解决它,但除此之外不多。
示例中的参数类型不是一个简单的类型参数,而是一个构造的泛型类型(它是使用方法的类型参数T构造的,但它的构造一样)。编译器需要进行两次推断才能找出T的值。首先,需要看到构造类型的泛型类型是TList<T>
的泛型类型的祖先;它还需要将构造类型的类型参数列表中的类型参数T与TList<T>
的祖先中的具体类型Integer进行匹配。