長話短說:下面這段代碼不能編譯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;
幾個錯誤消息從編譯器發出:
-
E2015:操作員不適用於此的操作數類型
上線
if T = TSomeComponent then
和 -
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:」, '' ;」或'>'預期但是':'找到
「編譯器不應該認識到,T是TComponent類型的,因爲我明確地約束了它?」不,它不會。通用約束不解析類型。它只是幫助編譯器*阻止*使用通用類型或過程,而不是約束類型。看到我的回答:https://stackoverflow.com/questions/43679740/test-if-an-interface-equals-a-type-parameter/43681952#43681952 –