【问题标题】:Generic methods type inference泛型方法类型推断
【发布时间】:2014-12-03 14:25:11
【问题描述】:

假设我有一个包含两个通用方法的类:

TMyClass = class
  procedure DoWith<T: class> (obj: T);
  procedure DoFor<T: class> ( proc: TProc<T> );
end;

现在,当我想使用特定类型参数调用这两个方法中的任何一个时,Delphi 可以推断DoWith 方法的类型,因此我可以使用其中任何一个调用它

MyClass.DoWith <TButton> ( MyButton )

MyClass.DoWith ( MyButton )

Delphi 编译器会很高兴地编译这两者。 但是如果我在DoFor 方法中省略了类型参数,Delphi 编译器就会抱怨缺少类型参数:

MyClass.DoFor<TButton>(procedure (Button: TButton) begin .... end);  // compiles


MyClass.DoFor(procedure (Button: TButton) begin .... end);  // doesn't compile

现在我的问题是:这只是编译器的一个缺点,还是有任何逻辑原因(我还没有弄清楚)阻止编译器正确推断 DoFor 方法的类型?

【问题讨论】:

  • 这看起来像是编译器的限制。 Delphi 中的泛型类型推断非常弱。

标签: delphi generics type-inference


【解决方案1】:

它无法从TProc&lt;T&gt;argument 推断T 的原因是当时TProc&lt;TButton&gt; 是一个构造类型,没有任何信息表明它最初是TProc&lt;T&gt;

要做到这一点,它必须从不起作用的匿名方法签名中推断出类型(我想 Barry Kelly 可以更好地解释这一点,我认为他曾经写过关于 lambdas 和 Delphi 中类型推断的困难)。

Delphi 编译器能够进行的唯一类型推断是 T 类型的参数。即使有多个不经常工作的参数,如果你有多个泛型类型参数,甚至更少。

编辑:我找到了一条评论,其中 Barry 解释了 Delphi 编译器中类型推断和 lambdas 的困难:http://www.deltics.co.nz/blog/posts/244/comment-page-1#comment-107

【讨论】:

  • 感谢 Stefan:您的回答让我明白了这个编译器行为是有逻辑原因的。
  • @iamjoosy 我个人觉得这不合逻辑。如果编译器能更好地推断类型,我会更喜欢它。我看不出它为什么不能这样做。许多其他语言在这方面的管理比 Delphi 好得多。
  • @DavidHeffernan 起初我自己在编译器行为中看不到任何逻辑,因此我在这里提出问题。但是 Stefan 的回答通过解释编译器如何处理表达式让我大开眼界:它从内到外构造实际类型,从而首先构造具有 TButton 类型的匿名函数,然后在周围的过程中使用该类型进行操作,此时编译器“忘记”了匿名函数是从装饰周围函数的相同类型参数 T 构造的。
  • @DavidHeffernan 这并不是说不能更好地处理,而是解释了为什么编译器在当前实现中存在问题。
  • @iamjoosy 在我看来,根据我的用法,编译器在推断泛型方面非常糟糕。很明显,这取决于它的实现方式。我个人认为说编译器的实现方式意味着它很蹩脚,这并不是很有见地。从问题中可以清楚地看出这一点。
猜你喜欢
  • 2017-09-08
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多