如何在 Delphi 中将特定类型的变量转换为泛型 T?
How to cast a variable of specific type to generic T in Delphi?
根据T的实际类型,我想return一个具体的值;这里是一个简化的例子(一些对象的记录包装器):
function TMyRec.TryGet<T>(const Default: T): T;
begin
if TypeInfo(T) = TypeInfo(TMyObject) then
Result:= FMyObject {E2010 Incompatible types}
else Result:= FMyObject.TryGet<T>(Default);
end;
很明显,我不能将 T
以外的任何内容分配给 Result
,并且 as T
或 T()
不起作用,当 T
是不限于 class
...
也无法进行仅在通用限制方面有所不同的重载:
function TryGet<T: TMyObject>(const Default: T): T; overload;
{...}
Result:= FMyObject as T; {here it would work}
为了帮助理解下面评论中的讨论,这里是我编辑之前的例子:
function TMyRec.TryGet<T>(const Default: T): T;
begin
if TypeInfo(T) = TypeInfo(TMyObject) then Result:= FMyObject
//else ...
else Result:= Default;
end;
我找到的唯一方法是使用 System.Rtti.TValue
(类型错误除外):
Result:= TValue.From(FMyObject).AsType<T>
或更短 ;-) 自动类型(returns 如果类型错误则为 false;您可以在此处忽略它,因为您已经检查过 TypeInfo):
TValue.From(FMyObject).TryAsType(Result)
建议:重新考虑你的概念; 泛型可能不是一个好的解决方案,但我们不能在不了解更多背景的情况下判断。
我相信这是实现您想要的效果的最佳方法(至少在性能方面)。
type
PMyObject = ^TMyObject;
function TMyRec.TryGet<T>(const Default: T): T;
begin
if TypeInfo(T) = TypeInfo(TMyObject) then
PMyObject(@Result)^ := FMyObject
else if TypeInfo(T) = TypeInfo(Integer) then
PInteger(@Result)^ := 1
//else ...
else
Result := Default;
end;
我正在使用 Delphi XE5。
将您的示例更改为:
function TryGet<T: class>(const Default: T): T; overload;
{...}
Result:= FMyObject as T; {here it will work}
变化是 TMyObject
到 class
。当你不是 "class" 它时,你会得到编译器错误 E2089.
根据T的实际类型,我想return一个具体的值;这里是一个简化的例子(一些对象的记录包装器):
function TMyRec.TryGet<T>(const Default: T): T;
begin
if TypeInfo(T) = TypeInfo(TMyObject) then
Result:= FMyObject {E2010 Incompatible types}
else Result:= FMyObject.TryGet<T>(Default);
end;
很明显,我不能将 T
以外的任何内容分配给 Result
,并且 as T
或 T()
不起作用,当 T
是不限于 class
...
也无法进行仅在通用限制方面有所不同的重载:
function TryGet<T: TMyObject>(const Default: T): T; overload;
{...}
Result:= FMyObject as T; {here it would work}
为了帮助理解下面评论中的讨论,这里是我编辑之前的例子:
function TMyRec.TryGet<T>(const Default: T): T;
begin
if TypeInfo(T) = TypeInfo(TMyObject) then Result:= FMyObject
//else ...
else Result:= Default;
end;
我找到的唯一方法是使用 System.Rtti.TValue
(类型错误除外):
Result:= TValue.From(FMyObject).AsType<T>
或更短 ;-) 自动类型(returns 如果类型错误则为 false;您可以在此处忽略它,因为您已经检查过 TypeInfo):
TValue.From(FMyObject).TryAsType(Result)
建议:重新考虑你的概念;
我相信这是实现您想要的效果的最佳方法(至少在性能方面)。
type
PMyObject = ^TMyObject;
function TMyRec.TryGet<T>(const Default: T): T;
begin
if TypeInfo(T) = TypeInfo(TMyObject) then
PMyObject(@Result)^ := FMyObject
else if TypeInfo(T) = TypeInfo(Integer) then
PInteger(@Result)^ := 1
//else ...
else
Result := Default;
end;
我正在使用 Delphi XE5。
将您的示例更改为:
function TryGet<T: class>(const Default: T): T; overload;
{...}
Result:= FMyObject as T; {here it will work}
变化是 TMyObject
到 class
。当你不是 "class" 它时,你会得到编译器错误 E2089.