如何在德尔福中将特定类型的变量转换为泛型 T?



根据 T 的实际类型,我想返回一个特定的值;这里有一个简化的例子(某个对象的记录包装器(:

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,并且当T不限于class时,as TT()不起作用......

也不可能执行仅在通用限制上有所不同的重载:

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>

或更短;-(使用自动类型(如果类型错误,则返回 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。

将 yoru 示例更改为:

function TryGet<T: class>(const Default: T): T; overload;
{...}
Result:= FMyObject as T; {here it will work}

此更改TMyObjectclass.当你不"类"它时,你会得到编译器错误E2089。

最新更新