将泛型类型变量转换为字符串

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;

使用多种类型(如 IntegerDoubleBoolean...)效果很好,但使用 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;

你可以,然后当TVariant时调用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 值类型是 tkUnknowntkArraytkRecordtkDynArray