Search code examples
delphigenericstypeinfo

How to cast a generic type into an actual type in Delphi


Consider the following code

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
......

I want to have a generic procedure that gets a generic value of type T and according to the actual type of T insert the value to an hashtable.

The compiler won't let me do this cast, also won't let me do something like Integer(Value).

Can someone please explain how should i implement the above?


Solution

  • Although you can do this type of thing easily with classes, it is not so easy with other types, like integers, strings and enums. Although they work with generics to an extent, they are not great. On the other hand, in this case you don't need to.

    Because generics are so useful there is a great temptation to rush into generics when they are not really needed (I know I have fallen into that trap more than once). All you need here is overloaded functions as is shown below.

    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.
    

    I have created a dummy class THashTable for the purposes of illustration only and I have not created FHashTable. This is simply to illustrate the principles. I know the code will not run as it stands, but it will compile.