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

Wer*_*ann 5 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;
Run Code Online (Sandbox Code Playgroud)

不知何故,编译器类型推断似乎在这里有问题:

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;
Run Code Online (Sandbox Code Playgroud)

第一个调用按预期工作,T正确推断为Integer.

第二个调用不起作用,除非我也添加<Integer> - 然后它可以工作,如第三次调用中所见.我做错了什么或Delphi中的类型推断只是不支持这个(我不认为它是Java中的一个问题,这也是为什么期望它在Delphi中工作).

Bar*_*lly 9

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

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