无法编译约束泛型方法

时间:2017-06-01 13:08:41

标签: delphi generics constraints delphi-10.1-berlin generic-constraints

长话短说:以下代码不能在 Delphi 10.1 Berlin(Update 2)中编译。

interface

uses
  System.Classes, System.SysUtils;

type
  TTest = class(TObject)
  public
    function BuildComponent<T: TComponent>(const AComponentString: String): T;
  end;

  TSomeComponent = class(TComponent)
  public
    constructor Create(AOwner: TComponent; const AString: String); reintroduce;
  end;

implementation

{ TTest }

function TTest.BuildComponent<T>(const AComponentString: String): T;
begin
  if T = TSomeComponent then
    Result := TSomeComponent.Create(nil, AComponentString)
  else
    Result := T.Create(nil);
end;

{ TSomeComponent }

constructor TSomeComponent.Create(AOwner: TComponent; const AString: String);
begin
  inherited Create(AOwner);
end;

编译器发出了几条错误消息:

  1.   

    E2015:运算符不适用于此操作数类型

    if T = TSomeComponent then行和

  2.   

    E2010不兼容的类型 - 'T'和'TSomeComponent'

    Result := TSomeComponent.Create(nil, AComponentString)行。

  3. 为了规避这些,我可以转发TClass(T)(#1},如LU RD's answer here中所述(尽管有人说,这个错误已经在 XE6 )和T(TSomeComponent.Create(nil, AComponentString))(#2)。虽然,我觉得使用显式类型转换感到不舒服。

    还有更好的方法吗?编译器不应该认识到,T属于TComponent类型,因为我明确约束了它吗?

    首先,我尝试声明泛型函数的实现,就像它的接口一样:

    function TTest.BuildComponent<T: TComponent>(const AComponentString: String): T;
    

    但最终出现了错误

      

    E2029:',',';'或'&gt;'预期但':'发现

1 个答案:

答案 0 :(得分:3)

这在我遇到的任何版本的Delphi中都无法编译。你需要做一些演员来说服编译器编译它:

function TTest.BuildComponent<T>(const AComponentString: String): T;
begin
  if TClass(T) = TSomeComponent then
    Result := T(TSomeComponent.Create(nil, AComponentString))
  else
    Result := T(TComponentClass(T).Create(nil));
end;

那就是说,我认为我可能更喜欢:

if TClass(T).InheritsFrom(TSomeComponent) then

代替那种平等测试。

即便如此,尝试将具有不同参数的新构造函数拼接到基于虚拟构造函数的类看起来对我来说也是一种灾难。