Can I determine the type of an array of different types?

I would like to define an array type, which consists of different types, such as String , Integer , Boolean , Double , etc., but not objects, structures, or anything like that. Then I would like to use this type as an argument to a function, 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 to determine the type of each element when repeating through such an array?

I am sure that this is possible, but does not even have a clue about what terminology to look for. How to do it?

Should I define this as an array of options? Or is there a way to determine which types the array accepts?

EDIT

Don't change the question, but after RRUZ's answer, I found an intriguing article on efficiency when I do this exact thing of the way ...

+7
arrays delphi delphi-xe2
source share
4 answers

If the Delphi version supports RTTI, you can use a TValue array and a Kind property like this.

 {$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 to use 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. 
+12
source share

Oddly enough, no one has yet mentioned variant recordings, which for decades have been a feature of Pascal:

 type TVarRecType = (vrtInteger, vrtDouble {other types go here}); TVarRec = record Field1: string; { can be omitted } case RecType: TVarRecType of vrtInteger: IntValue: integer; vrtDouble: DblValue: double; { other cases go here } end; var VarRec: TVarRecType; begin VarRec.Field1 := 'This is an example.'; VarRec.RecType := vrtInteger; VarRec.IntValue := 4711; {...} VarRec.RecType := wrtDouble; VarRec.DblValue := Pi; {...} end; { Oops, forgot the array part } type TVarRecArr = array[1..15] of TVarRec; var VarRecArr: TVarRecArr; begin VarRecArr[1].Field1 := 'This is the first record'; VarRecArr[1].RecType := wrtInteger; VarRecArr[1].IntValue := 1; {...} end; 
+2
source share

Arrays are homogeneous. As the documentation says:

An array represents an indexed collection of elements of the same type (called the base type).

Therefore, you can achieve your goal only with a base type that can store different types of data. This type of data is known as a data variant .

Delphi has a number of options for data type options. There is the venerable COM Variant type. A new child appeared on the block, TValue , which was added to support the new RTTI style. And there are many third-party options. Typically, these third-party options exist to support conservation infrastructures.

+1
source share

Since you can use the array of const construct to use as a parameter. Also known as open array options. Read more about my answer to this other question .

It works as your desired array of different types. Docwiki Delphi documentation on this topic

0
source share

All Articles