2

长话短说:下面这段代码不能编译Delphi 10.1柏林(更新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'

    on line Result := TSomeComponent.Create(nil, AComponentString)

为了规避这些,我能投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:”, '' ;”或'>'预期但是':'找到

+1

“编译器不应该认识到,T是TComponent类型的,因为我明确地约束了它?”不,它不会。通用约束不解析类型。它只是帮助编译器*阻止*使用通用类型或过程,而不是约束类型。看到我的回答:https://stackoverflow.com/questions/43679740/test-if-an-interface-equals-a-type-parameter/43681952#43681952 –

回答

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 

到位平等的测试。

即使这样,试图在具有不同参数的新构造函数中拼接到基于虚拟构造函数的类看起来像是对我而言灾难的秘诀。

+0

我更喜欢'InheritsFrom'测试。事实上,我不会给新组件一个不同的构造函数。我会使用属性来代替。然后,BuildComponent可能不再是通用的,他可以传递一个TComponentClass(也可能是一个所有者)。或者也许他可以完全没有它。 –