通用方法类型推断

6

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

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中的通用类型推断非常弱。 - David Heffernan
1个回答

5
它无法从TProc参数中推断出T的原因在于此时TProc是一个构造类型,没有任何信息表明它最初是TProc。要做到这一点,它必须从匿名方法签名中推断出类型,但这并不起作用(我想Barry Kelly可能能更好地解释这一点,并且我认为他曾经写过关于Delphi中lambda和类型推断困难的文章)。Delphi编译器唯一能够推断的类型是T类型的参数。甚至对于多个参数也经常不起作用,如果你有多个泛型类型参数,则会更少。编辑:我找到了Barry解释有关类型推断和Delphi编译器中lambda困难性的评论的地方:http://www.deltics.co.nz/blog/posts/244/comment-page-1#comment-107

谢谢Stefan:你的回答给了我理解这个编译器行为的缺失部分,让我明白了其中的逻辑原因。 - iamjoosy
2
@iamjoosy 我个人觉得这个不合逻辑。如果编译器能更好地推断类型,我会更喜欢。我看不出为什么它不能这样做。许多其他语言比Delphi在这方面做得更好。 - David Heffernan
@iamjoosy 根据我的经验,我认为编译器在泛型推断方面的表现相当差劲。很明显,这是由其实现方式造成的。我个人并不觉得说编译器的实现方式非常糟糕很有启发性。这一点从问题中就非常清楚了。 - David Heffernan
@Stefan 我不太同意。当然,这很困难,但这就是实际情况。你回答中的文本试图解释编译器的弱点,并且在我看来似乎表现出有些内在的东西意味着它无法完成。事实上,答案应该是,“这很难做,Embarcadero开发人员决定不解决这个问题”。通过保留编译器的当前弱形式,他们只会在成千上万的代码库中传播混乱的代码。如果解决了这个问题,将会有巨大的回报。 - David Heffernan
我猜Delphi开发人员和PHP开发人员处于同一水平线上。 - David Heffernan
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接