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?
Try something like this:
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
......
Or this:
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
......
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With