AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Remove in Generic TObjectList

Ein Thema von SteffenSchm · begonnen am 3. Nov 2008 · letzter Beitrag vom 3. Nov 2009
Antwort Antwort
Seite 1 von 2  1 2      
SteffenSchm

Registriert seit: 2. Nov 2004
Ort: Herzogenaurach
84 Beiträge
 
Delphi 10.3 Rio
 
#1

Remove in Generic TObjectList

  Alt 3. Nov 2008, 10:42
Hallo alle zusammen,

nachdem ich mir Delphi2009 gekauft und installiert habe, wollte ich die generischen Listen der neuen Version nutzen. Ich habe also die Objectlisten (TObjectList) durch generische (z.B. TObjectList<TRecord>) ersetzt. Damit wollte ich mir Typkonvertierungen beim Zugriff auf Elemte der Liste ersparen.

Der Compiler hat das ganze auch ohne Fehlermeldung compiliert. Als ich aber in meinem Programm den Menüpunkt zum Löschen eines einzelnen Elementes der Liste aufgerufen habe, kam eine AV. Das Löschen sollte über Remove erfolgen.

Das prinzipielle Problem habe ich in folgendem Testprogramm dargestellt. Bei Aufruf von Remove innerhalb Button2Click kommt die AV. Löschen über Delete funktioniert dagegen.

Delphi-Quellcode:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Generics.Collections, Dialogs, StdCtrls;

type
  TForm3 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  TRecord = class(TObject)
    Name:String;
    X,Y:Double;
  end;

var
  Form3: TForm3;
  RecLst : TObjectList<TRecord>;

implementation
{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
  I: Integer;
  Rec:TRecord;
begin
  for I := 0 to 4 do
  begin
    Rec:=TRecord.Create;
    Rec.X:=Random;
    Rec.Y:=Random;
    RecLst.Add(Rec);
  end;
end;

procedure TForm3.Button2Click(Sender: TObject);
var
  Rec:TRecord;
begin
  Rec:=RecLst[0];
  RecLst.Remove(Rec);
end;

initialization
  RecLst :=TObjectList<TRecord>.Create;
finalization
  RecLst.Free;
end.
Kann mir jemand sagen, wo der Fehler liegt. Habe ich etwa das ganze Thema mit den Generics falsch verstanden?

Bin für jeden Hinweis dankbar!
Steffen
  Mit Zitat antworten Zitat
Hawkeye219

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

Re: Remove in Generic TObjectList

  Alt 3. Nov 2008, 20:14
Hallo,

wenn ich das richtig verstanden habe, benötigt die Objektliste einen comparer zum Auffinden von Elementen - auch bei IndexOf().
Da ich aber selbst gerade dabei bin, meine ersten Gehversuche mit Delphi 2009 zu machen, wäre es gut, wenn ein "Wissender" den folgenden Code einmal prüfen könnte.

Delphi-Quellcode:
// uses Generics.Defaults

function CompareNames (const Left, Right: TRecord): Integer;
begin
  Result := CompareText(Left.Name, Right.Name);
end;

initialization
  RecLst := TObjectList<TRecord>.Create (
    TComparer<TRecord>.Construct(CompareNames)
  );
finalization
  RecLst.Free;
end.
Gruß Hawkeye
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#3

Re: Remove in Generic TObjectList

  Alt 3. Nov 2008, 20:46
Zitat von Hawkeye219:
wenn ich das richtig verstanden habe, benötigt die Objektliste einen comparer zum Auffinden von Elementen - auch bei IndexOf().
Das ist genau richtig! Und der Code tut's auch...
Uwe Raabe
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#4

Re: Remove in Generic TObjectList

  Alt 3. Nov 2008, 21:19
[OT]
Zitat von Hawkeye219:
wenn ich das richtig verstanden habe, benötigt die Objektliste einen comparer zum Auffinden von Elementen - auch bei IndexOf().
Logisch ist das schon, aber es kann doch nicht sein, dass das mit einer AV beantwortet wird ?
[/OT]
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Dax
(Gast)

n/a Beiträge
 
#5

Re: Remove in Generic TObjectList

  Alt 3. Nov 2008, 21:21
Zitat von Khabarakh:
[OT]
Zitat von Hawkeye219:
wenn ich das richtig verstanden habe, benötigt die Objektliste einen comparer zum Auffinden von Elementen - auch bei IndexOf().
Logisch ist das schon, aber es kann doch nicht sein, dass das mit einer AV beantwortet wird ?
[/OT]
Es ist eine effektive Demonstration der Ausgereiftheit von Generics in Delphi.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Remove in Generic TObjectList

  Alt 3. Nov 2008, 23:10
Ich kann mir nicht vorstellen, dass TObjectList sich so einfach Records unterschieben lassen.
Man muss Objekte in TObjectList speichern, weil in der Methode Remove intern <dasobjectausderliste>.Free; aufgerufen wird.
Verweisst der Zeiger nicht auf ein richtiges Objekt, knallt es bei .Free
In deinem Fall wäre TList die richtige Basisklasse.
  Mit Zitat antworten Zitat
Dax
(Gast)

n/a Beiträge
 
#7

Re: Remove in Generic TObjectList

  Alt 3. Nov 2008, 23:13
Heisst das etwa, dass Delphi generische Parameter ungeprüft annimmt und einfach aufs geratewohl irgendwelche Pointer aufruft?
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#8

Re: Remove in Generic TObjectList

  Alt 4. Nov 2008, 06:10
Schon Update #1 eingespielt? In der Fix-Liste sind ein paar Einträge zu Generics vorhanden.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
SteffenSchm

Registriert seit: 2. Nov 2004
Ort: Herzogenaurach
84 Beiträge
 
Delphi 10.3 Rio
 
#9

Re: Remove in Generic TObjectList

  Alt 4. Nov 2008, 07:26
Hallo zusammen,

danke für Eure Hinweise und Diskussion.

Das Update #1 habe ich gestern eingespielt. Am Verhalten in dem beschriebenen Fall hat sich aber nichts geändert.

Der Objectliste werden keine Records übergeben. Obwohl die Struktur irreführenderweise Record heisst, ist es eine Klasse (siehe Deklaration).

Wenn ich das ganze mit einer TObjectList ohne Generics mache klappt es ohne Probleme. Ich muss dann aber bei jedem Zugriff auf ein Objekt der Liste eine Typumwandlung machen. Also z.B.

Rec:=TRecord(RecLst[0]);

Das wollte ich mir eigentlich sparen !
Steffen
  Mit Zitat antworten Zitat
SteffenSchm

Registriert seit: 2. Nov 2004
Ort: Herzogenaurach
84 Beiträge
 
Delphi 10.3 Rio
 
#10

Re: Remove in Generic TObjectList

  Alt 23. Jul 2009, 13:47
Nach längerer Zeit hat mich dieser Punkt wieder einmal geärgert. Ich habe das Thema in QualityCentral eingestellt (#75853) und einen Verweis auf ein bereits diskutiertes Thema bekommen (#67272) - dort war auch der Grund für die Fehlermeldung und eine Abhilfe zu finden. Falls es jemand interessiert, dann versuche ich es mal mit meinen Worten zu beschreiben:

Der Fehler liegt in der Unit Generics.Collections im Constructor von TObjectList<T>:
Delphi-Quellcode:
constructor TObjectList<T>.Create(AOwnsObjects: Boolean);
begin
  inherited;
  FOwnsObjects := AOwnsObjects;
end;
TObjectList<T> ist von TList<T> abgeleitet. In der Klasse TList<T> gibt es aber keinen Constructor mit einem Parameter AOwnsObject. Damit läuft der Aufruf inherited ins Leere (und erzeugt auch keinen Compiler-Fehler !). Das heisst TObjectList wird nicht initialsiert und es wird kein auch keine Comparer erzeugt (dies geschieht eigentlich in TList.Create). Damit erzeugen alle nachfolgenden Aufrufe wie etwa
Delphi-Quellcode:
ObjectList.Extract(Obj)
ObjectList.Remove(Obj)
ObjectList.IndexOf(Obj)
eine AV.

Lösungen:

- Korrektur in Generics.Collections.pas:
Delphi-Quellcode:
constructor TObjectList<T>.Create(AOwnsObjects: Boolean);
begin
  inherited Create();
  FOwnsObjects := AOwnsObjects;
end;
oder
- Meiden des Aufrufs
  ObjectList := TObjectList<TNewObject>.Create; stattdessen:
  ObjectList := TObjectList<TNewObject>.Create(TComparer<TNewObject>.Default); Wie schon gesagt, die Lösung kommt nicht von mir, sondern wurde von Anfrey Tsiruljov und Wang Rui (die ich hier zumindest erwähnen möchte) in QualityCentral gestellt.
Mich wundert nur, dass der Fehler nicht in einem Delphi Update behoben wurde, da diese Fehler-Reports schon einige Monate alt sind.
Steffen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 02:02 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