将泛型类型变量转换为字符串
Converting a generic type variable to string
我正在尝试将 T
类型的泛型变量转换为 string
。
TMyTest = class
class function GetAsString<T>(const AValue : T) : string; static;
end;
...
uses
System.Rtti;
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
Result := TValue.From<T>(AValue).ToString();
end;
使用多种类型(如 Integer
、Double
、Boolean
...)效果很好,但使用 Variant
变量时“失败”。
procedure TForm1.FormCreate(Sender: TObject);
var
Tmp : Variant;
begin
Tmp := 123;
ShowMessage(TMyTest.GetAsString<Variant>(Tmp));
end;
它产生以下输出:
(variant)
我期待 VarToStr
函数获得相同的输出(但我不能将该函数与通用变量一起使用):
123
您可以检查 T
是否变体,然后在 AsVariant
函数上使用 VarToStr
。
您可以轻松地扩展该功能以适应 ToString
不会给您预期结果的其他类型。
uses
System.TypInfo, System.Rtti;
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
if PTypeInfo(TypeInfo(T)).Kind = tkVariant then
Result := VarToStr(TValue.From<T>(AValue).AsVariant)
else
Result := TValue.From<T>(AValue).ToString();
end;
你可以,然后当T
是Variant
时调用VarToStr()
,例如:
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
if TypeInfo(T) = TypeInfo(Variant) then begin
// yes, the following cast looks odd, but the compiler can't validate
// T is really a Variant in this context, as it syntax-checks the code
// *before* instantiating the Generic, so a runtime cast is needed.
// The TypeInfo check above will ensure the cast is safe...
Result := VarToStr({AValue}PVariant(@AValue)^);
end else begin
Result := TValue.From<T>(AValue).ToString;
end;
end;
或者,在 XE7+ 中,您可以改用 GetTypeKind()
内部函数:
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
if GetTypeKind(T) = tkVariant then begin
Result := VarToStr({AValue}PVariant(@AValue)^);
end else begin
Result := TValue.From<T>(AValue).ToString;
end;
end;
这两种方法都允许编译器通过从可执行文件中删除未使用的分支来优化代码,因为两种比较都被视为编译时常量。
注意:TValue.ToString
不支持的其他 TTypeKind
值类型是 tkUnknown
、tkArray
、tkRecord
和 tkDynArray
。
我正在尝试将 T
类型的泛型变量转换为 string
。
TMyTest = class
class function GetAsString<T>(const AValue : T) : string; static;
end;
...
uses
System.Rtti;
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
Result := TValue.From<T>(AValue).ToString();
end;
使用多种类型(如 Integer
、Double
、Boolean
...)效果很好,但使用 Variant
变量时“失败”。
procedure TForm1.FormCreate(Sender: TObject);
var
Tmp : Variant;
begin
Tmp := 123;
ShowMessage(TMyTest.GetAsString<Variant>(Tmp));
end;
它产生以下输出:
(variant)
我期待 VarToStr
函数获得相同的输出(但我不能将该函数与通用变量一起使用):
123
您可以检查 T
是否变体,然后在 AsVariant
函数上使用 VarToStr
。
您可以轻松地扩展该功能以适应 ToString
不会给您预期结果的其他类型。
uses
System.TypInfo, System.Rtti;
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
if PTypeInfo(TypeInfo(T)).Kind = tkVariant then
Result := VarToStr(TValue.From<T>(AValue).AsVariant)
else
Result := TValue.From<T>(AValue).ToString();
end;
你可以T
是Variant
时调用VarToStr()
,例如:
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
if TypeInfo(T) = TypeInfo(Variant) then begin
// yes, the following cast looks odd, but the compiler can't validate
// T is really a Variant in this context, as it syntax-checks the code
// *before* instantiating the Generic, so a runtime cast is needed.
// The TypeInfo check above will ensure the cast is safe...
Result := VarToStr({AValue}PVariant(@AValue)^);
end else begin
Result := TValue.From<T>(AValue).ToString;
end;
end;
或者,在 XE7+ 中,您可以改用 GetTypeKind()
内部函数:
class function TMyTest.GetAsString<T>(const AValue : T) : string;
begin
if GetTypeKind(T) = tkVariant then begin
Result := VarToStr({AValue}PVariant(@AValue)^);
end else begin
Result := TValue.From<T>(AValue).ToString;
end;
end;
这两种方法都允许编译器通过从可执行文件中删除未使用的分支来优化代码,因为两种比较都被视为编译时常量。
注意:TValue.ToString
不支持的其他 TTypeKind
值类型是 tkUnknown
、tkArray
、tkRecord
和 tkDynArray
。