3

长话短说:以下代码在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)

为了规避这些,我可以转换TClass(T)(对于#1),如LU RD在这里的回答中所述(尽管据说这个错误已经在XE6中修复)和T(TSomeComponent.Create(nil, AComponentString))(对于#2)。虽然,我对使用显式类型转换感到不舒服。

有没有更好的办法?编译器不应该识别,因为我明确限制了它T的类型吗?TComponent


起初,我尝试将泛型函数的实现声明为它的接口:

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

但这以错误告终

E2029: ',', ';' 或 '>' 预期但 ':' 找到

4

1 回答 1

4

这不会在我遇到的任何版本的 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

代替那个平等测试。

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

于 2017-06-01T13:18:07.970 回答