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(也可能是一個所有者)。或者也許他可以完全沒有它。 –