我想定义一个由不同类型组成的数组类型,例如String,Integer,Boolean,Double等,但没有对象,结构或任何这种性质.然后我想将此类型用作函数参数,例如……
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;
并像…一样使用它
Variable:= GetSomething(['some string',123,'something else',12.3,false]);
那么,在迭代这样一个数组时,如何识别每个元素的类型?
我很确定这是可能的,但甚至不知道要搜索什么术语.我该怎么做呢?
我是否必须将其定义为Variants数组?或者有没有办法确定数组接受哪些类型?
编辑
不要改变任何问题,但在RRUZ的答案之后,我发现了an intriguing article关于性能的不同方式……
解决方法
如果你的Delphi版本支持RTTI,你可以使用
TValue
的数组和Kind属性.
{$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',false]); except on E: Exception do Writeln(E.ClassName,': ',E.Message); end; Readln; end.
另一种选择是使用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',E.Message); end; Readln; end.