![]() |
Kann man "X: array of array of const" realisieren?
Hallo zusammen.
Ich habe verschiedene Klassen die Objektlisten verwalten. Dabei haben einige Listen Unterlisten. Alle Listen haben gemeinsam, dass Starteinträge zur Programmierzeit bereits feststehen. Ich möchte daher dem Kontruktor diese Starteinträge mit auf den Weg geben. Für die Listen ohne Unterlisten sieht der Kontruktur beispielhaft so aus:
Delphi-Quellcode:
Ich hätte auch gern den Listen mit Unterlisten die Starteinträge dem Konstruktor übergeben; etwa so:
TMyObjectList1 = class(TObjectList)
... constructor Create(const Items: array of const); ... end; constructor TMyObjectList1.Create(const Items: array of const); var Index: Integer; begin inherited Create; for Index := 0 to High(Items) do if Items[Index].VType = vtObject then Add(Items[Index].VObject) else Exception.Create('Typ des Elements im Array-Parameter kann nicht verarbeitet werden.'); end;
Delphi-Quellcode:
Das würde es gestatten eine Liste auf höherer Ebene wie folgt zu erzeugen:
TMyObjectList2 = class(TObjectList)
... constructor Create(const Items: array of const); ... end; constructor TMyObjectList2.Create(const Items: array of const); var Index: Integer; begin inherited Create; for Index := 0 to High(Items) do if Items[Index].VType = {?}...{/?} then Add(TMyObjectList1.Create({?}Items[Index]{/?})) else Exception.Create('Typ des Elements im Array-Parameter kann nicht verarbeitet werden.'); end;
Delphi-Quellcode:
Momentan ist das Erzeugen und Befüllen der Listen ein Wust aus Variablen, Kontruktoren und Add-Funktionen.
MyObjectList:=TMyObjectList.Create([
[ [TObject1.Create(...),TObject2.Create(...),TObject3.Create(...)], [TObject1.Create(...),TObject4.Create(...),TObject4.Create(...),TObject5.Create(...)] ], [ [TObject1.Create(...),TObject6.Create(...)], [TObject7.Create(...),TObject7.Create(...)], // ... ], // ... ]); Aber wenn ich versuche ein Array, wie oben gezeigt, als Parameter zu übergeben, teilt mir der Compiler beim ersten Unterelement-Array mit: "Ordinaltyp erforderlich." Gibt es eine Möglichkeit die Unterelement-Arrays sicher als Ordinaltyp zu kaschieren? Gruß, Panthrax. |
Re: Kann man "X: array of array of const" realisie
Versuchs mal mit inem "ZwischenTyp"
Delphi-Quellcode:
Type
ConstArray=Array of Const; ... X: Array of ConstArray |
Re: Kann man "X: array of array of const" realisie
Soetwas wie
Delphi-Quellcode:
kann nicht deklariert werden.
type
TArrayOfConst = array of const; Und, um es gleich vorweg zu nehmen: Auch soetwas hilft nicht weiter:
Delphi-Quellcode:
Delphi möchte in jedem Fall beim Unterarray einen Ordinaltyp haben. Eine dreiste Typumwandlung mit Integer(...), TObject(...), Pointer(...) usw. mekert der Compiler auch nur an: "Ungültige Typumwandlung."
type
TArrayOfVariant = array of Variant; Irgendwelche anderen Ideen? Gruß, Panthrax. |
Re: Kann man "X: array of array of const" realisie
Hallo Panthrax,
[equote="D7 OH - Topic 'Variante offene Array-Parameter'"]... array of const ist zur Konstruktion array of TVarRec äquivalent. ...[/equote] daraus schließe ich, dass du die Variable X aus dem Titel deines threads alternativ so deklarieren kannst - ohne dass der Compiler sich beschwert:
Delphi-Quellcode:
Inwieweit das eine Lösung für dein im Text formuliertes Problem sein kann, habe ich mir noch nicht überlegt.
var
X: array of array of TVarRec; Grüße vom marabu |
Re: Kann man "X: array of array of const" realisie
Zitat:
Zitat:
Deshalb meine Frage: Kann man diese inneren Arrays mit Typen kaschieren, die der Compiler akzeptiert? Mit den Erkenntnissen von oben könnte man die Fragen auch so formulieren: Wie kann man ein "array of" in einem TVarRec unterbringen (damit dieser wiederum als "array of"-Element fungieren kann)? Eine Notation wie "[[...], [...],...]" würde mir den Quelltext an diesen Stellen ordentlich aufräumen. Wie gesagt, momentan ist das ein "Wust aus Variablen, Kontruktoren und Add-Funktionen", um die Listen mit den Startwerten zu befüllen. Es gibt leider auch keine Regelmäßigkeit unter den Elementen, die ich nutzen könnte, das in eine Schleife zu packen. Gruß, Panthrax. |
Re: Kann man "X: array of array of const" realisie
Hallo Panthrax,
mit einer Hilfsfunktion, welche deine Objekte temporär in eine Liste packt, kommst du vielleicht doch noch ans Ziel:
Delphi-Quellcode:
Da die Liste selbst wieder ein Objekt ist, kannst du die Aufrufe von NewList schachteln:
function NewList (const aItems: array of TObject): TList;
var i : Integer; begin Result := TList.Create; for i := 0 to High(aItems) do Result.Add(aItems[i]); end;
Delphi-Quellcode:
Auch wenn das ganze sehr kompakt aussieht, die Lösung birgt Gefahren. Die verarbeitende Routine kann nicht zwischen "normalen" Objekten und Hilfslisten unterscheiden, falls die Objekte selbst von TList abgeleitet sind. Sollte dies notwendig sein, muß auch die Hilfsliste von TList abgeleitet werden, die Überprüfung erfolgt dann mit Hilfe des Operators IS. Weiterhin ist darauf zu achten, daß die temporären Listen wieder freigegeben werden, sonst enstehen Memleaks. Neben diesen Problemen entsteht durch den Aufbau der Listen ein kleiner Overhead, der aber wahrscheinlich vernachlässigt werden kann.
HandleItems (
NewList([ NewList([ TObject.Create, TObject.Create, TObject.Create ]), NewList([ TObject.Create, TObject.Create ]), NewList([ TObject.Create, TObject.Create, TObject.Create, TObject.Create ]) ]) ); Eine andere Möglichkeit wäre die Verwendung von dynamischen Arrays:
Delphi-Quellcode:
Es ist etwas mehr Schreibarbeit beim Aufruf, aber die oben genannten Probleme werden vermieden.
type
TObjectMatrix = array of array of TObject; var Items : TObjectMatrix; begin SetLength (Items, 3), SetLength (Items[0], 3); Items[0, 0] := TObject.Create; Items[0, 1] := TObject.Create; Items[0, 2] := TObject.Create; SetLength (Items[1], 2); Items[1, 0] := TObject.Create; Items[1, 1] := TObject.Create; SetLength (Items[2], 4); Items[2, 0] := TObject.Create; Items[2, 1] := TObject.Create; Items[2, 2] := TObject.Create; Items[2, 3] := TObject.Create; HandleItems (Items); end; procedure HandleItems (const aItems: TObjectMatrix); var i, j : Integer; begin for i := 0 to High(aItems) do for j := 0 to High(aItems[i]) do { verarbeite Objekt an Position (i, j) } end; Gruß Hawkeye |
Re: Kann man "X: array of array of const" realisie
TRY THIS:
Delphi-Quellcode:
Alles klar ?!
type
TConstArray= array of const; ... //you need this function function CopyVarRec(const Item: TVarRec): TVarRec; var W: WideString; begin // Copy entire TVarRec first Result := Item; // Now handle special cases case Item.VType of vtExtended: begin New(Result.VExtended); Result.VExtended^ := Item.VExtended^; end; vtString: begin New(Result.VString); Result.VString^ := Item.VString^; end; vtPChar: Result.VPChar := StrNew(Item.VPChar); // there is no StrNew for PWideChar vtPWideChar: begin W := Item.VPWideChar; GetMem(Result.VPWideChar, (Length(W) + 1) * SizeOf(WideChar)); Move(PWideChar(W)^, Result.VPWideChar^, (Length(W) + 1) * SizeOf(WideChar)); end; // a little trickier: casting to string will ensure // reference counting is done properly vtAnsiString: begin // nil out first, so no attempt to decrement // reference count Result.VAnsiString := nil; string(Result.VAnsiString) := string(Item.VAnsiString); end; vtCurrency: begin New(Result.VCurrency); Result.VCurrency^ := Item.VCurrency^; end; vtVariant: begin New(Result.VVariant); Result.VVariant^ := Item.VVariant^; end; // casting ensures proper reference counting vtInterface: begin Result.VInterface := nil; IInterface(Result.VInterface) := IInterface(Item.VInterface); end; // casting ensures a proper copy is created vtWideString: begin Result.VWideString := nil; WideString(Result.VWideString) := WideString(Item.VWideString); end; vtInt64: begin New(Result.VInt64); Result.VInt64^ := Item.VInt64^; end; // VPointer and VObject don't have proper copy semantics so it // is impossible to write generic code that copies the contents end; end; //and you need this function //CCA = CreateConstArray function CCA(const Elements: array of const): TConstArray; var I: Integer; begin SetLength(Result, Length(Elements)); for I := Low(Elements) to High(Elements) do Result[I] := CopyVarRec(Elements[I]); end; //yours constructor constructor TMyObjectList2.Create(Items: array of const); //yours call to constructor := TMyObjectList2.Create([ CCA([TObject.Create]), CCA([TObject.Create, TObject.Create]), ... ]); ciao Radek |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz