【问题标题】:Why is Delphi unable to infer the type for a parameter TEnumerable<T>?为什么 Delphi 无法推断参数 TEnumerable<T> 的类型?
【发布时间】:2010-04-25 23:34:50
【问题描述】:

考虑以下 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。

第二次调用不起作用,除非我也添加&lt;Integer>——然后​​它起作用,正如第三次调用所示。我做错了什么还是 Delphi 中的类型推断不支持这一点(我认为这不是 Java 中的问题,这也是为什么期望它也可以在 Delphi 中工作的原因)。

【问题讨论】:

    标签: delphi generics type-inference


    【解决方案1】:

    编译器需要进行模式匹配来推断参数类型;目前没有。编译器仅限于非常简单的推理 - 如果参数类型是类型参数类型,那么编译器可以计算出来,但仅此而已。

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

    【讨论】:

    • 在这种情况下,如果说 Delphi 类型推理实现勉强足以保证将其作为“新功能”包含在盒子中,是否过于苛刻?被认为是有意义的“功能完整”?
    • 有时“刚刚好”真的不够好 - 完全没有东西比拥有不会嘎嘎,不会蹒跚而行,只能勉强游泳的东西要好never-the-less 到处称自己为“鸭子”。 “更好”的意思是它不会导致这种问题/混乱,从而引起人们对“功能差距”的关注,并为那些试图将 Delphi 视为过时/也在运行的人提供弹药。最好说:“类型推断不符合 Pascal 的本质”——恕我直言,这是一个完全正确且有效的立场。
    • 谢谢,巴里。看来我必须忍受它。也许明年...... ;-) 如果可以的话,一个与此相关的小问题:我应该将这个 utils 类基于 IEnumerable 而不是 TEnumerable?对我来说似乎更通用,并且帮助声明 IEnumerable 不必在具有 GetEnumerator 方法的类上声明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2022-08-03
    • 2014-12-27
    • 1970-01-01
    相关资源
    最近更新 更多