如何在 Delphi 中将泛型类型转换为实际类型

ita*_*312 4 delphi generics typeinfo

考虑以下代码

procedure TMyClass.SetParam<T>(Name: string; Value: T);
begin
  if (TypeInfo(T) = TypeInfo(string)) then
  begin
    FHashTable.AddString(Name, (Value as string));
  end
  else if (TypeInfo(T) = TypeInfo(Integer)) then
  begin
    FHashTable.AddInteger(Name, (Value as Integer));
  end
......
Run Code Online (Sandbox Code Playgroud)

我想要一个通用过程,它获取类型 T 的通用值,并根据 T 的实际类型将值插入到哈希表中。

编译器不会让我做这个转换,也不会让我做像 Integer(Value) 这样的事情。

有人可以解释一下我应该如何实现上述内容吗?

Rem*_*eau 5

尝试这样的事情:

procedure TMyClass.SetParam<T>(Name: string; Value: T);
begin
  if (TypeInfo(T) = TypeInfo(string)) then
  begin
    FHashTable.AddString(Name, PString(@Value)^);
  end
  else if (TypeInfo(T) = TypeInfo(Integer)) then
  begin
    FHashTable.AddInteger(Name, PInteger(@Value)^);
  end
......
Run Code Online (Sandbox Code Playgroud)

或这个:

uses
  System.Rtti;

procedure TMyClass.SetParam<T>(Name: string; Value: T);
var
  LValue: TValue;
begin
  LValue := TValue.From<T>(Value);
  if (TypeInfo(T) = TypeInfo(string)) then
  begin
    FHashTable.AddString(Name, LValue.AsString);
  end
  else if (TypeInfo(T) = TypeInfo(Integer)) then
  begin
    FHashTable.AddInteger(Name, LValue.AsInteger);
  end
......
Run Code Online (Sandbox Code Playgroud)


Dsm*_*Dsm 5

尽管您可以使用类轻松完成此类操作,但使用其他类型(例如整数、字符串和枚举)却并不那么容易。尽管它们在一定程度上可以与泛型一起使用,但它们并不是很好。另一方面,在这种情况下您不需要这样做。

因为泛型非常有用,所以当实际上不需要泛型时,很容易急于使用泛型(我知道我不止一次陷入这个陷阱)。这里您所需要的只是重载函数,如下所示。

unit UnitTest1;

interface

type
  THashTable = class
    procedure AddString( const pName : string; pValue : string ); virtual; abstract;  // dummy for illustration only
    procedure AddInt( const pName : string; const pInt : integer ); virtual; abstract;  // dummy for illustration only
  end;

  TMyClass = class
  private
    FHashTable : THashTable;
  public
    procedure TestString;
    procedure TestInt;

    procedure SetParam( const pName : string; const pValue : string ); overload;
    procedure SetParam( const pName : string; const pValue : integer ); overload;

  end;

implementation

{ TMyClass }

procedure TMyClass.SetParam(const pName, pValue: string);
begin
  FHashTable.AddString( pName, pValue );
end;

procedure TMyClass.SetParam(const pName: string; const pValue: integer);
begin
  FHashTable.AddInt( pName, pValue );
end;

procedure TMyClass.TestInt;
begin
  SetParam( 'Int', 4 );
end;

procedure TMyClass.TestString;
begin
  SetParam( 'Int', 'Fred' );
end;

end.
Run Code Online (Sandbox Code Playgroud)

我创建了一个虚拟类 THashTable 仅用于说明目的,并且没有创建 FHashTable。这只是为了说明原理。我知道代码不会按原样运行,但它会编译。