I'd like to define an array type which consists of different type values, such as String
, Integer
, Boolean
, Double
, etc. but no objects, structures, or anything of that nature. Then I'd like to use this type as a function argument, for example...
type
TMyArray = array of ...?...;
function GetSomething(const Input: TMyArray): String;
var
X: Integer;
begin
for X:= 0 to Length(Input) - 1 do begin
//Identify type and handle accordingly...
//Serialize data for the result...
end;
end;
and use it like...
Variable:= GetSomething(['some string', 123, 'something else', 12.3, false]);
Then, how do I identify what type each element is when iterating through such an array?
I'm pretty sure this is possible, but have no idea even what terminology to search for. How do I do this?
Would I have to define this as an array of Variants? Or is there a way to define exactly which types the array accepts?
EDIT
Not to change the question any, but after the answer by RRUZ, I found an intriguing article about the performance when doing this exact thing different ways...
If your Delphi version supports RTTI, you can use an array of TValue
and the Kind
property like so.
{$APPTYPE CONSOLE}
uses
System.TypInfo,
System.Rtti,
System.SysUtils;
function GetSomething(const Input: array of TValue): String;
var
X: Integer;
LValue : TValue;
begin
for LValue in Input do begin
case LValue.Kind of
tkUnknown: Writeln('Unknown');
tkInteger: Writeln(Format('The Kind of the element is Integer and the value is %d',[LValue.AsInteger]));
tkChar: Writeln('Char');
tkEnumeration: if LValue.TypeInfo=TypeInfo(Boolean) then Writeln(Format('The Kind of the element is Boolean and the value is %s',[BoolToStr(LValue.AsBoolean, True)]));
tkFloat: Writeln(Format('The Kind of the element is Float and the value is %n',[LValue.AsExtended]));
tkString: Writeln('String');
tkSet: Writeln('Set');
tkClass: Writeln('Class');
tkMethod:Writeln('method');
tkWChar: Writeln('WChar');
tkLString: Writeln('String');
tkWString: Writeln('String');
tkVariant: Writeln('Variant');
tkArray: Writeln('Array');
tkRecord: Writeln('Record');
tkInterface: Writeln('Interface');
tkInt64: Writeln('Int64');
tkDynArray: Writeln('DynArray');
tkUString: Writeln(Format('The Kind of the element is String and the value is %s',[LValue.AsString]));
tkClassRef: Writeln('Class Ref');
tkPointer: Writeln('Pointer');
tkProcedure: Writeln('procedure');
end;
end;
end;
begin
try
GetSomething(['some string', 123, 'something else', 12.3, false]);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Another option is use an array of const
{$APPTYPE CONSOLE}
uses
SysUtils;
procedure GetSomething(const Input: array of const);
var
LIndex: Integer;
begin
for LIndex := Low(Input) to High(Input) do
begin
case Input[LIndex].VType of
vtWideString: Writeln('WideString = ''', WideString(Input[LIndex].VWideChar), '''');
vtInt64: Writeln('Int64 = ', Input[LIndex].VInt64^);
vtCurrency: Writeln('Currency = ', CurrToStr(Input[LIndex].VCurrency^));
vtInteger: Writeln('Integer = ', Input[LIndex].VInteger);
vtBoolean: Writeln('Boolean = ', BoolToStr(Input[LIndex].VBoolean, True));
vtChar: Writeln('Char = ''', Input[LIndex].VChar, '''');
vtExtended: Writeln('Extended = ', FloatToStr(Input[LIndex].VExtended^));
vtString: Writeln('ShortString = ''', Input[LIndex].VString^, '''');
vtPChar: Writeln('PChar = ''', Input[LIndex].VPChar, '''');
vtAnsiString: Writeln('AnsiString = ''', Ansistring(Input[LIndex].VAnsiString), '''');
vtWideChar: Writeln('WideChar = ''', Input[LIndex].VWideChar, '''');
vtPWideChar: Writeln('PWideChar = ''', Input[LIndex].VPWideChar, '''');
vtUnicodeString : Writeln('UnicodeString = ''', string(Input[LIndex].VUnicodeString), '''');
else
Writeln('Unsupported');
end;
end;
end;
begin
try
GetSomething(['some string', 123, 'something else', 12.3, false]);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.