无法编译受约束的泛型方法
Cannot compile constrained generic method
长话短说:以下代码无法在 Delphi 10.1 Berlin(更新 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: Operator not applicable to this operand type
线上 if T = TSomeComponent then
和
-
E2010 Incompatible types - 'T' and 'TSomeComponent'
线上 Result := TSomeComponent.Create(nil, AComponentString)
.
为了避免这些问题,我可以按照 LU RD's answer here 中的描述施放 TClass(T)
(对于 #1)(尽管据说这个错误已经在 中得到修复) XE6)和T(TSomeComponent.Create(nil, AComponentString))
(对于#2)。虽然,我对使用显式类型转换感到不舒服。
有什么更好的方法吗?编译器不应该识别 T
是 TComponent
类型因为我明确地限制了它吗?
起初,我尝试像声明接口一样声明泛型函数的实现:
function TTest.BuildComponent<T: TComponent>(const AComponentString: String): T;
但这以错误告终
E2029: ',', ';' or '>' expected but ':' found
这不会在我遇到的任何版本的 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
代替相等性测试。
即便如此,尝试将具有不同参数的新构造函数拼接到基于虚拟构造函数的 class 对我来说仍然是灾难的根源。
长话短说:以下代码无法在 Delphi 10.1 Berlin(更新 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: Operator not applicable to this operand type
线上
if T = TSomeComponent then
和 -
E2010 Incompatible types - 'T' and 'TSomeComponent'
线上
Result := TSomeComponent.Create(nil, AComponentString)
.
为了避免这些问题,我可以按照 LU RD's answer here 中的描述施放 TClass(T)
(对于 #1)(尽管据说这个错误已经在 中得到修复) XE6)和T(TSomeComponent.Create(nil, AComponentString))
(对于#2)。虽然,我对使用显式类型转换感到不舒服。
有什么更好的方法吗?编译器不应该识别 T
是 TComponent
类型因为我明确地限制了它吗?
起初,我尝试像声明接口一样声明泛型函数的实现:
function TTest.BuildComponent<T: TComponent>(const AComponentString: String): T;
但这以错误告终
E2029: ',', ';' or '>' expected but ':' found
这不会在我遇到的任何版本的 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
代替相等性测试。
即便如此,尝试将具有不同参数的新构造函数拼接到基于虚拟构造函数的 class 对我来说仍然是灾难的根源。