AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Kann man "X: array of array of const" realisieren?

Kann man "X: array of array of const" realisieren?

Ein Thema von Panthrax · begonnen am 16. Dez 2006 · letzter Beitrag vom 17. Dez 2006
Antwort Antwort
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#1

Kann man "X: array of array of const" realisieren?

  Alt 16. Dez 2006, 17:00
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:
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;
Ich hätte auch gern den Listen mit Unterlisten die Starteinträge dem Konstruktor übergeben; etwa so:
Delphi-Quellcode:
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;
Das würde es gestatten eine Liste auf höherer Ebene wie folgt zu erzeugen:
Delphi-Quellcode:
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(...)],
    // ...
  ],
  // ...
]);
Momentan ist das Erzeugen und Befüllen der Listen ein Wust aus Variablen, Kontruktoren und Add-Funktionen.

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.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Kann man "X: array of array of const" realisie

  Alt 16. Dez 2006, 17:09
Versuchs mal mit inem "ZwischenTyp"

Delphi-Quellcode:
Type
    ConstArray=Array of Const;
    
...
X: Array of ConstArray
Markus Kinzler
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#3

Re: Kann man "X: array of array of const" realisie

  Alt 16. Dez 2006, 17:28
Soetwas wie
Delphi-Quellcode:
type
  TArrayOfConst = array of const;
kann nicht deklariert werden.

Und, um es gleich vorweg zu nehmen: Auch soetwas hilft nicht weiter:
Delphi-Quellcode:
type
  TArrayOfVariant = array of Variant;
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."

Irgendwelche anderen Ideen?

Gruß,
Panthrax.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#4

Re: Kann man "X: array of array of const" realisie

  Alt 16. Dez 2006, 19:18
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:
var
  X: array of array of TVarRec;
Inwieweit das eine Lösung für dein im Text formuliertes Problem sein kann, habe ich mir noch nicht überlegt.

Grüße vom marabu
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#5

Re: Kann man "X: array of array of const" realisie

  Alt 17. Dez 2006, 10:34
Zitat von marabu:
ohne dass der Compiler sich beschwert:
Delphi-Quellcode:
var
  X: array of array of TVarRec;
Das ist soweit richtig.
Zitat:
Inwieweit das eine Lösung für dein im Text formuliertes Problem sein kann, habe ich mir noch nicht überlegt.
Das Problem ist die Notation: Mit "[...]" kann man einen "array of"-Parameter übergeben aber kein Element eines "array of" im Quelltext notieren; à la "[[...], [...],...]". Der Compiler verlangt als Arrayelement einen Ordinaltyp ("Ordinaltyp erforderlich.").

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.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#6

Re: Kann man "X: array of array of const" realisie

  Alt 17. Dez 2006, 12:18
Hallo Panthrax,

mit einer Hilfsfunktion, welche deine Objekte temporär in eine Liste packt, kommst du vielleicht doch noch ans Ziel:

Delphi-Quellcode:
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;
Da die Liste selbst wieder ein Objekt ist, kannst du die Aufrufe von NewList schachteln:

Delphi-Quellcode:
HandleItems (
  NewList([
    NewList([
      TObject.Create,
      TObject.Create,
      TObject.Create
      ]),
    NewList([
      TObject.Create,
      TObject.Create
      ]),
    NewList([
      TObject.Create,
      TObject.Create,
      TObject.Create,
      TObject.Create
      ])
    ])
  );
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.


Eine andere Möglichkeit wäre die Verwendung von dynamischen Arrays:

Delphi-Quellcode:
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;
Es ist etwas mehr Schreibarbeit beim Aufruf, aber die oben genannten Probleme werden vermieden.

Gruß Hawkeye
  Mit Zitat antworten Zitat
radekj

Registriert seit: 17. Dez 2006
22 Beiträge
 
#7

Re: Kann man "X: array of array of const" realisie

  Alt 17. Dez 2006, 15:50
TRY THIS:

Delphi-Quellcode:
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]),
                          ...
                         ]);
Alles klar ?!

ciao
Radek
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz