AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi TList und record: Auf Variablen zugreifen
Thema durchsuchen
Ansicht
Themen-Optionen

TList und record: Auf Variablen zugreifen

Ein Thema von Sascha L · begonnen am 6. Sep 2006 · letzter Beitrag vom 7. Nov 2006
Antwort Antwort
Sascha L

Registriert seit: 4. Jun 2004
Ort: Hamm
390 Beiträge
 
Delphi 2006 Professional
 
#1

TList und record: Auf Variablen zugreifen

  Alt 6. Sep 2006, 12:41
Hallo,

habe folgenden Code:

Delphi-Quellcode:
TFeedItem = record
    Title,
    Description,
    Author,
    URL : String;
    DateTime : TDateTime;
  end;

  TFeedItemClass = class(TPersistent)
    private
      fItems: TList;
      function GetItem(Index: Integer): TFeedItem;
      procedure SetItem(Index: Integer; const FeedItem: TFeedItem);
      function GetCount: Integer;
    public
      constructor Create;
      destructor Destroy; override;
      procedure AddItem(const FeedItem: TFeedItem);
      procedure RemoveItem(Index: Integer);
      procedure Clear;
      property Items[Index: Integer]: TFeedItem read GetItem write SetItem;
      property Count: Integer read GetCount;
  end;

function TFeedItemClass.GetItem(Index: Integer): TFeedItem;
begin
  Result := TFeedItem(fItems[Index]^);
end;

procedure TFeedItemClass.SetItem(Index: Integer; const FeedItem: TFeedItem);
begin
  fItems[Index] := @FeedItem;
end;
Nun ist es möglich, dass ich z.B. folgendes machen kann:

Delphi-Quellcode:
var
  Item: TFeedItem;
begin
  Item.Title := 'sdfsdf';
  FeedItemClass.Items[5] := Item;
end;
Damit würde das 5. Item mit den neuen Daten überschrieben werden. (In diesem Beispiel existiert das 5. Item natürlich!)

Es ist aber nicht möglich folgendes zu machen:

  FeedItemClass.Items[5].Title := 'sdfsdfs'; Da meckert der Compiler, dass auf Title nur lesend zugegriffen werden kann.

Wo muss ich nun was anpassen, damit ich normal auf die Variablen zugreifen kann?

Gruß
Sascha
Sascha
  Mit Zitat antworten Zitat
KrasserChecker

Registriert seit: 21. Jul 2004
120 Beiträge
 
#2

Re: TList und record: Auf Variablen zugreifen

  Alt 6. Sep 2006, 12:49
Du solltest nie "records" als Properties verwenden. durch die interne Speicherverwaltung wird nämlich nie auf die eigentlichen Speicherbereiche verwiesen, sondern nur auf Kopien.
Daher empfehel ich dir die Struktur "TFeedItem" in eine Klasse umzuwandeln & in der Klasse "TFeedItemClass" statt "TList" "TObjectList" zu verwenden.
"TObjectList" verwaltet Objekte - sprich gibt deren Speicherbereiche auch korrekt wieder frei.
  Mit Zitat antworten Zitat
marabu

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

Re: TList und record: Auf Variablen zugreifen

  Alt 6. Sep 2006, 12:57
Hallo Sascha,

die korrekte Art des Zugriffs hast du selbst schon gezeigt. Das Problem beim direkten Setzen von Title ist die Tatsache, dass du gar nicht auf einen record zugreifst, sondern auf eine function - nur die Notation .Items[5]. gaukelt dir den Zugriff auf eine Struktur TFeedItem vor.

Delphi-Quellcode:
var
  // ...
  FeedItem: TFeedItem;
begin
  // ...
  FeedItem := FeedItemClass.Items[5];
  FeedItem.Title := 'sdfsdfs';
end;
Grüße vom marabu
  Mit Zitat antworten Zitat
Sascha L

Registriert seit: 4. Jun 2004
Ort: Hamm
390 Beiträge
 
Delphi 2006 Professional
 
#4

Re: TList und record: Auf Variablen zugreifen

  Alt 6. Sep 2006, 13:09
Danke

Ich habe es nun aus TFeedItem eine Klasse gebaut und nun klappt es auch alles einwandfrei

Nur das erste Beispiel funktioniert nur noch teilweise, was auch logisch ist:

Delphi-Quellcode:
var
  Item: TFeedItem;
begin
  Item := TFeedItem.Create;
  Item.Title := 'sdfsdf';
  FeedItemClass.Items[5] := Item;
end;
Das klappt nun. Muss ich aber nun nicht selbst noch Item wieder freigeben, oder wird das später automatisch gemacht? Denn wenn ich am Ende des Codes Item.Free mache, dann ist es auch unter Items[] nicht mehr drin bzw. nur noch leere Strings. Reicht es aus, wenn ich in der SetItem-Methode eine neue Klasse erzeuge und das übermittelte Item dort übergebe, sodass ich es außerhalb auch ohne Probleme freigeben kann?

edit: ok, es reicht nicht aus bzw. klappt so auch nicht...
Sascha
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#5

Re: TList und record: Auf Variablen zugreifen

  Alt 6. Sep 2006, 17:45
Hallo,

ich hatte mir das damals einfacher gemacht,
indem ich eine eigene Listen-Klasse (TListEx)
und eine Basisklasse für alle Einträge dieser Liste
gebaut habe (TListItemEx).

Im destructor der TListEx steht dann

Delphi-Quellcode:
{ Listenelemente freigeben }
destructor TListEx.Destroy;
begin
  try
    ClearList;
    inherited Destroy;
  except
  end;
end; { TListEx.Destroy }


procedure TListEx.ClearList;
var
  iItem : Integer;
  Item : TListItemEx;
begin
  try
    for iItem:= Count-1 downto 0 do
    begin
      Item:= Items[iItem];
      Delete(iItem);

     { free, if we have the original pointer here }
      if (bHasLinks=False) then
      begin
        FreeAndNIL(Item);
      end;
    end
  except
  end;
end;
Alle Klassen werden von TListItemEx abgeleitet.

#edit#
FreeAndNil kann auch durch Item.Free ersetzte werden.
Der Destructor ist in Wirklichkeit aber etwas länger, ich benutze das NIL.
Das bHasLinks ist ien property, was wenn es True ist, die Klasse selber nicht freigibt,
sondern nur aus der Liste löscht.
Heiko
Heiko
  Mit Zitat antworten Zitat
KrasserChecker

Registriert seit: 21. Jul 2004
120 Beiträge
 
#6

Re: TList und record: Auf Variablen zugreifen

  Alt 6. Sep 2006, 19:01
Wie bereits geschrieben verwaltet TObjectList die enthaltenen Objekte. D.h., dass sie beim Freigeben alle enthaltenen Objekte mit freigibt. Du brauchat (und darfst) die Objekte vom Typ "TFeedItem" NICHT selbst freigeben (wenn sie einmal in der TObjectList enthalten sind).

Die Methode von oben würde wie folgt aussehen:

Delphi-Quellcode:
var
  Item: TFeedItem;
begin
  Item := TFeedItem.Create;
  Item.Title := 'sdfsdf';
  FeedItemClass.AddItem(Item);
end;
Außerdem würde ich die Methode "SetItem" entfernen, da Du dir mit soetwas evt. die Zeiger auf ein bereits vorhandenes Objekt überschreibst. Dessen Speicherbereich ist dann "vergessen" und vor allem: verloren.

Die Methode "GetItem" sieht natürlich so aus:

Delphi-Quellcode:
function TFeedItemClass.GetItem(Index: Integer): TFeedItem;
begin
  Result := FItems[Index] as TFeedItem;
end;
  Mit Zitat antworten Zitat
schöni

Registriert seit: 23. Jan 2005
Ort: Dresden
445 Beiträge
 
Delphi 7 Personal
 
#7

Re: TList und record: Auf Variablen zugreifen

  Alt 7. Nov 2006, 19:08
Hallo!

Ich habe hier das Problem, das ich einerseits in der Compare_ Funktion eine EInvalidOp Exception erhalte, andererseits auch noch eine EInvalidOp

Delphi-Quellcode:
type
  PObjStruct = ^TObjStruct;
  TObjStruct = record
    useability,mass,optimum: Extended;
  end;
  TObjects = class(TList)
    function Add(Item: Pointer): Integer;
  end;

function TObjects.Add(Item: Pointer): Integer;
begin
   PObjStruct(Item).optimum := PObjStruct(Item)^.useability / PObjStruct(Item)^.mass;
   Result := inherited Add(PObjStruct(Item));
end;

function Compare_(Item1,Item2: Pointer): Integer;
begin
 if PObjStruct(Item1)^.optimum < PObjStruct(Item2)^.optimum then Result := -1 else
 if PObjStruct(Item1)^.optimum > PObjStruct(Item2)^.optimum then Result := +1 else //EInvalidOp in der zweiten Vergleichsoperation
 Result := 0;
end;

procedure Optimize(var AObjects,AList: TList; AMaxMass: Extended);
var i,j: Integer; amass: Extended;
begin
  amass := 0.0;
  AList.Sort(Compare_);
  i := AList.Count-1;
  while i > 0 do
  begin
    amass := amass + PObjStruct(AList.Items[i])^.mass; //EInvalidOp
    if amass<=AMaxMass then AObjects.Add(PObjStruct(AList.Items[i])) else
    begin
      j:=i;
      while (amass>AMaxMass) and (j>0) do
      begin
        amass := amass - PObjStruct(AList.Items[j])^.mass;
        amass := amass + PObjStruct(AList.Items[j-1])^.mass;
        if amass<=AMaxMass then AObjects.Add(PObjStruct(AList.Items[j-1]));
        Dec(j);
      end;
    end;
    Dec(i);
  end;
end;
Ich habe mich hier mal drangemacht, das Rucksackproblem zu lösen, das ein anderes Mitglied der DP hier erfragt hatte als ich vor einigen Tagen seit langem mal wieder hier vorbeigeschaut habe. Die Procedure Optimize hat folgende Parameter:

AObjects: Die fertige Liste mit den Objekten, die die Gewichtsschranke einhalten
AList: Die Liste mit den Objekten, aus denen passende ausgewählt werden
AMaxMass: Die Gewwichtsschranke

Leider hänge ich nun fest am Probelem des Zugriffs auf die Recordvariablen in der liste.
Wer kann mir hier helfen? Sobald das Problem gelöst ist, soll die Optimize-Prozedur hier in die CodeLibrary aufgenommen werden.

schöni
Damit der Topf nicht explodiert, lässt man es ab und zu mal zischen.
  Mit Zitat antworten Zitat
schöni

Registriert seit: 23. Jan 2005
Ort: Dresden
445 Beiträge
 
Delphi 7 Personal
 
#8

Re: TList und record: Auf Variablen zugreifen

  Alt 7. Nov 2006, 19:52
Habe in der Optimize Prozedur die Listentypen auf TObjects gesetzt. Nun Klappt's.
Damit der Topf nicht explodiert, lässt man es ab und zu mal zischen.
  Mit Zitat antworten Zitat
Antwort Antwort


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 06:56 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