为什么Delphi无法推断参数TEnumerable <t>?</t>的类型

时间:2010-04-25 23:34:50

标签: delphi generics type-inference

在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中工作)。

1 个答案:

答案 0 :(得分:9)

编译器需要进行模式匹配以推断参数类型;它目前没有。编译器仅限于非常简单的推理 - 如果参数类型是类型参数类型,那么编译器可以解决它,但除此之外不多。

示例中的参数类型不是一个简单的类型参数,而是一个构造的泛型类型(它是使用方法的类型参数T构造的,但它的构造一样)。编译器需要进行两次推断才能找出T的值。首先,需要看到构造类型的泛型类型是TList<T>的泛型类型的祖先;它还需要将构造类型的类型参数列表中的类型参数T与TList<T>的祖先中的具体类型Integer进行匹配。