Einzelnen Beitrag anzeigen

Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#1

Typinformationen bei Mix aus statischen und dyn. Arrays

  Alt 19. Jun 2011, 00:15
Hallo zusammen,

bin gerade dabei eine Methode zu schreiben, die den "Basistyp" für einen gegebenen Array-Typen ausgibt. Beispiel: Bei array of Integer soll tkInteger (TTypeKind) herauskommen bzw. eine Referenz auf TypeInfo(Integer) . Hier mal die aktuelle Methode:
Delphi-Quellcode:
function GetArrayBaseType(const ArrayTypeInfo: PTypeInfo; out BaseTypeKind: TTypeKind; out BaseTypeInfo: PTypeInfo): Boolean; overload;
var
  TD : PTypeData;
  BaseType : PTypeInfo;
begin
  if (ArrayTypeInfo = nil) or (not (ArrayTypeInfo.Kind in [tkArray, tkDynArray])) then
    Exit(False);
  TD := GetTypeData(ArrayTypeInfo);

  if (ArrayTypeInfo.Kind = tkArray) then
  begin
    if (TD.ArrayData.ElType = nil) or (TD.ArrayData.ElType^ = nil) then
      Exit(False);
    BaseType := TD.ArrayData.ElType^;
  end
  else begin
    if ((TD.elType = nil) or (TD.elType^ = nil)) and ((TD.elType2 = nil) or (TD.elType2^ = nil)) then
      Exit(False);
    if ((TD.elType = nil) or (TD.elType^ = nil)) then
      BaseType := TD.elType2^
    else
      BaseType := TD.elType^;
  end;

  if (BaseType.Kind in [tkArray, tkDynArray]) then
    Result := GetArrayBaseType(BaseType, BaseTypeKind, BaseTypeInfo)
  else begin
    BaseTypeKind := BaseType.Kind;
    BaseTypeInfo := BaseType;
    Result := True;
  end;
end;
Und hier das kleine Testprogramm dazu:
Delphi-Quellcode:
function GetArrayBaseTypeInfo(const ArrayTypeInfo: PTypeInfo): PTypeInfo; overload;
var
  TK : TTypeKind;
begin
  if (not GetArrayBaseType(ArrayTypeInfo, TK, Result)) then
    raise Exception.Create('Could not read base type info of given array.');
end;

type
  TDynArray = array of Integer;
  TGenericArray = TArray<String>;
  TBlub = TArray<TArray<TArray<Variant>>>;
  TMatrix = array[0..3, 0..3] of Extended;
  THugeMatrix = array[0..3, 0..3] of array[0..3, 0..3] of Char;
  TDynMatrixA = array of array[0..3, 0..3] of Int64;
  TDynMatrixB = array[0..3, 0..3] of array of array[0..3, 0..3] of Int64;
begin
  Writeln(GetArrayBaseTypeInfo(TypeInfo(TDynArray)).Name);
  Writeln(GetArrayBaseTypeInfo(TypeInfo(TGenericArray)).Name);
  Writeln(GetArrayBaseTypeInfo(TypeInfo(TMatrix)).Name);
  Writeln(GetArrayBaseTypeInfo(TypeInfo(THugeMatrix)).Name); // <- hier hagelt es dann eine Exception
  Writeln(GetArrayBaseTypeInfo(TypeInfo(TBlub)).Name);

  Writeln(GetArrayBaseTypeInfo(TypeInfo(TDynMatrixA)).Name);
  Writeln(GetArrayBaseTypeInfo(TypeInfo(TDynMatrixB)).Name);
Das Programm läuft bis zum vorletzten Schritt, der ein "Mixed" Array (hier TDynMatrixA) behandelt, bestehend aus einem statischen und einem dynamischen Teil. Der erste Schritt in der Rekursion von GetArrayBaseType scheitert schon, da GetTypeData() quasi nichts sinnvolles an Daten liefert, siehe Screenshot. Nimmt der Compiler bei sowas interne Optimierungen vor, sodass ich via RTTI hier nicht wirklich was ausrichten kann? Oder woher könnte das Problem sonst noch kommen? Gibt es vielleicht einen anderen Weg an den Basistyp eines Arrays zu gelangen? Kann ja auch gut sein, dass ich hiermit auf dem Holzpfad bin...
Miniaturansicht angehängter Grafiken
screenshot.png  
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat