![]() |
TObjectList als Result
Habe ein kleines Programm geschrieben das eine TObjectList als REsult nehmen soll nur jedes mal wenn ich den Button drücke hat er mir fehler raus das er auf bestimmte speicher nicht zugreifen kann oder das da was nicht stimmt.
bitte um hilfe
Delphi-Quellcode:
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Contnrs, JPeg; type TForm1 = class(TForm) Image1: TImage; Image2: TImage; Image3: TImage; Image4: TImage; Image5: TImage; Image6: TImage; Image7: TImage; Allrounder : TImage; Button1: TButton; procedure Button1Click(Sender: TObject); function imageloader : TObjectList; private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} function TForm1.imageloader: TObjectList; begin Result.Create; Result.Add(Image1); Result.Add(Image2); Result.Add(Image3); Result.Add(Image4); Result.Add(Image5); Result.Add(Image6); Result.Add(Image7); end; procedure TForm1.Button1Click(Sender: TObject); var MyList: TObjectlist; counter : integer; begin Mylist := ImageLoader; Allrounder := TImage(Imageloader.Items[5]); Allrounder.Picture.LoadFromFile('Unbenannt.jpg'); end; end. |
AW: TObjectList als Result
Zitat:
Delphi-Quellcode:
Hatten wir das nicht erst letzte Woche? Übrigens sollte man im Allgemeinen keine Objektinstanzen aus Funktionen zurückgeben, die innerhalb derer erst angelegt werden. Wo wird die Liste samt der enthaltenen Objekte denn wieder freigegeben?
Result := TObjectList.Create;
|
AW: TObjectList als Result
Wieso nicht?
Delphi-Quellcode:
NeueListe := FunktionIrgendwas();
try finally NeueListe.Free; end; |
AW: TObjectList als Result
Und wenn Du Dir das nach 6 Monaten noch einmal anschaust, wunderst Du Dich, dass da eine Freigabe erfolgt, ohne dass vorher ein Konstruktoraufruf ersichtlich ist, denn der steht ja woanders, womöglich noch in einer ganz anderen Unit.
|
AW: TObjectList als Result
Wenn man der Funktion einen aussagekräftigen Namen gibt anhand dem ersichtlich ist, dass das Objekt darin erstellt wird sehe ich da kein Problem. Aber ich denke das ist Geschmackssache.
|
AW: TObjectList als Result
Hier habe ich mich mal mit dem Thema beschäftigt:
![]() |
AW: TObjectList als Result
Da hier die Referenzen nicht in der Liste verwaltet werden, verwende ich bei sowas gern dynamische Arrays als Result.
|
AW: TObjectList als Result
![]() Klar gehen die erst ab Delphi 2010 aber es dürfte ja ein leichtes sein, sich ne schlanke TInterfacedObjectList mit entsprechendem Interface zu bauen, wenn man mit nem älteren Delphi hantiert. |
AW: TObjectList als Result
Früher gab es IInterfaceList bzw. IInterfaceListEx in der Classes-Unit.
|
AW: TObjectList als Result
Zitat:
|
AW: TObjectList als Result
Zitat:
|
AW: TObjectList als Result
Zitat:
Eine ![]()
Delphi-Quellcode:
.
IInterface
Eine
Delphi-Quellcode:
soll für Items vom Typ
TInterfacedObjectList
Delphi-Quellcode:
sein.
TObject
|
AW: TObjectList als Result
Zitat:
|
AW: TObjectList als Result
Zitat:
Nur dass sich diese bekannte
Delphi-Quellcode:
als Rückgabewert einer Funktion etwas ungeschickt ist (wegen der evtl. zu erwartenden Speicherlecks). Darum der (gute) Vorschlag von Stevie statt einer
TObjectList
Delphi-Quellcode:
ein
TObjectList
Delphi-Quellcode:
zurückzugeben, was die gleichen Eigenschaften, wie
Interface
Delphi-Quellcode:
hat, sich aber (weil es ja ein
TObjectList
Delphi-Quellcode:
ist) von selber wieder aus dem Speicher entfernt, sobald da niemand mehr den Finger drauf hat.
Interface
Da hinter einem
Delphi-Quellcode:
immer (mindestens) eine konkrete Klasse steht war der Vorschlag diese Klasse einfach
Interface
Delphi-Quellcode:
zu nennen.
TInterfacedObjectList
|
AW: TObjectList als Result
// Edit
Jetzt hat es bei mir Klick gemacht! Es geht darum einen Wrapper um TObjectList zu stricken, der per Interface ansprechbar ist. Der Weg, eine Classes.IInterfaceList zu benutzen und die betreffenden Klassen mit einen Interface zu versehen ginge aber auch. Wäre am Ende sogar weniger Code. |
AW: TObjectList als Result
Zitat:
Delphi-Quellcode:
Und dann im seinem Quelltext
unit Unit1;
interface uses Contnrs, Classes; type IObjectList = interface ['{056BC23C-2F12-40DF-A0F7-2A9AE55ADADB}'] function Add( AObject: TObject ): Integer; function Extract( Item: TObject ): TObject; function ExtractItem( Item: TObject; Direction: TList.TDirection ): TObject; function Remove( AObject: TObject ): Integer; overload; function RemoveItem( AObject: TObject; ADirection: TList.TDirection ): Integer; function IndexOf( AObject: TObject ): Integer; function IndexOfItem( AObject: TObject; ADirection: TList.TDirection ): Integer; function FindInstanceOf( AClass: TClass; AExact: Boolean = True; AStartAt: Integer = 0 ): Integer; procedure Insert( Index: Integer; AObject: TObject ); function First: TObject; function Last: TObject; function GetOwnsObjects: Boolean; procedure SetOwnsObjects( const Value: Boolean ); property OwnsObjects: Boolean read GetOwnsObjects write SetOwnsObjects; function GetItem( Index: Integer ): TObject; procedure SetItem( Index: Integer; AObject: TObject ); property Items[Index: Integer]: TObject read GetItem write SetItem; default; end; TInterfacedObjectList = class( TObjectList, IInterface, IObjectList ) private // IInterface FRefCount: Integer; function QueryInterface( const IID: TGUID; out Obj ): HRESULT; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; private // IObjectList function GetOwnsObjects: Boolean; procedure SetOwnsObjects( const Value: Boolean ); end; implementation { TInterfacedObjectList } function TInterfacedObjectList.GetOwnsObjects: Boolean; begin Result := OwnsObjects; end; function TInterfacedObjectList.QueryInterface( const IID: TGUID; out Obj ): HRESULT; begin if GetInterface( IID, Obj ) then Result := 0 else Result := E_NOINTERFACE; end; procedure TInterfacedObjectList.SetOwnsObjects( const Value: Boolean ); begin OwnsObjects := Value; end; function TInterfacedObjectList._AddRef: Integer; begin Result := AtomicIncrement( FRefCount ); end; function TInterfacedObjectList._Release: Integer; begin Result := AtomicDecrement( FRefCount ); if Result = 0 then Destroy; end; end.
Delphi-Quellcode:
function TForm1.imageloader: IObjectList;
begin Result := TInterfacedObjectList.Create( False ); Result.Add(Image1); Result.Add(Image2); Result.Add(Image3); Result.Add(Image4); Result.Add(Image5); Result.Add(Image6); Result.Add(Image7); end; procedure TForm1.Button1Click(Sender: TObject); var MyList: IObjectlist; counter : integer; begin Mylist := ImageLoader; // Jetzt Interface, jetzt keine Speicherlecks mehr Allrounder := TImage(Imageloader.Items[5]); // <- da wird schon wieder eine erzeugt!!!, aber ist ja JETZT kein Problem mehr Allrounder.Picture.LoadFromFile('Unbenannt.jpg'); end; |
AW: TObjectList als Result
Zitat:
|
AW: TObjectList als Result
Wären dann aber nicht auch anschließend die TImages weg? Ich tendiere in diesem Fall eher zu himitsus Vorschlag mit dem dynamischen Array, das erfordert weniger Aufwand und sollte vollkommen ausreichend sein.
|
AW: TObjectList als Result
Zitat:
Delphi-Quellcode:
Das mit den Arrays kommt auf den Einsatzzweck an (hier bestimmt völlig ausreichend). Es macht aber nichts, so eine Interface-ObjectList in der Hinterhand zu haben, vor allem, wenn man die LifeTime der Elemente damit verwalten will. Keiner mehr Interesse an der Liste, dann alles ab in die Tonne :)
Result := TInterfacedObjectList.Create(
{OwnsObjects} False ); |
AW: TObjectList als Result
Schon lustig, dieser Thread :lol:
Der TE stellt eine Frage. Was er mit diesem Code will, ist garnicht wirklich klar. Er hat auch keine Antwort geschrieben. Es wird hier aber trotzdem weiter philosophiert ;-) Wie Ihr auf den ganzen Interface-Kram kommt, kann ich nicht wirklich nachvollziehen. Ist zwar interessant, hat aber mit dem Problem des TE nichts zu tun. Oder? Edit: Bis Beitrag #7 war es noch themenbezogen. |
AW: TObjectList als Result
Der Beste Code ist nicht immer der passende Code. Wenn man sich die Fragen des TE mal durchliest, wird man Sehen, dass er diese Lösung hier schon im Ansatz nicht verstehen wird, da ihm ja offensichtlich die Grundlagen dafür fehlen.
Den Verweis auf das Schlißen derselbigen wird konsequent ignoriert. Eigentlich scheinen sich alle Fragen, um das selbe Programm/Problem zu drehen. |
AW: TObjectList als Result
@bernau
Die Lösung kam schon mit der ersten Antwort, und der Rest handelt von den Seiteneffekten (Speicherlecks). |
AW: TObjectList als Result
Zitat:
|
AW: TObjectList als Result
Die Frage für mich ist, warum erzeugt der TE ein Form, zieht dort acht TImages (Image1 bis Image7 und Allrounder) drauf, die beim erzeugen des Formulars alle instanziert sind, und überschreibt kurz gefasst "Allrounder" mit "Image5". Ein Stück Code der für mich keinen Sinn macht.
|
AW: TObjectList als Result
Zitat:
|
AW: TObjectList als Result
Viel Diskussion um das Thema, aber auf den zweiten Fehler ist niemand direkt eingegangen:
Zitat:
Und die zweite kann man bei dieser Art des Aufrufs auch nicht mehr freigeben.
Delphi-Quellcode:
Abgesehen davon währe ein Property mit Index hier sinnvoller:
Mylist := ImageLoader;
try Allrounder := TImage(Mylist[5]); finally MyList.Free; end;
Delphi-Quellcode:
TForm1 = class(TForm)
Image1: TImage; Image2: TImage; Image3: TImage; Image4: TImage; Image5: TImage; Image6: TImage; Image7: TImage; Allrounder : TImage; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } function GetImageLoader(AIndex: Integer): TImage; public { Public-Deklarationen } property ImageLoader[AIndex: Integer]: TImage read GetImageLoader; end; implementation function TForm1.GetImageLoader(AIndex: Integer): TImage; begin {alternativ FindComponent} case AIndex of 0: Result := Image1; 1: Result := Image2; 2: Result := Image3; {...} 6: Result := Image7; else raise Exception.CreateFmt('ungültiger Index: GetImageLoader(%d)', [AIndex]); end; end; begin Allrounder := ImageLoader[5]; Allrounder.Picture.LoadFromFile('Unbenannt.jpg'); end; |
AW: TObjectList als Result
Zitat:
dann direkt folgendes
Delphi-Quellcode:
begin
ImageLoader[5].Picture.LoadFromFile('Unbenannt.jpg'); end; |
AW: TObjectList als Result
Aber noch mal. Der TE äussert sich nicht. Damit weis keiner, was wirklich gewollt ist.
|
AW: TObjectList als Result
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:28 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