Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   TObjectList als Result (https://www.delphipraxis.net/182468-tobjectlist-als-result.html)

Kuehter 27. Okt 2014 14:46

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.

DeddyH 27. Okt 2014 14:48

AW: TObjectList als Result
 
Zitat:

Delphi-Quellcode:
Result.Create;

-->
Delphi-Quellcode:
Result := TObjectList.Create;
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?

Neutral General 27. Okt 2014 14:57

AW: TObjectList als Result
 
Wieso nicht?

Delphi-Quellcode:
NeueListe := FunktionIrgendwas();
try

finally
  NeueListe.Free;
end;

DeddyH 27. Okt 2014 15:07

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.

Neutral General 27. Okt 2014 15:11

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.

DeddyH 27. Okt 2014 15:12

AW: TObjectList als Result
 
Hier habe ich mich mal mit dem Thema beschäftigt: http://www.detlef-heibing.de/program...rueckgabe.html

himitsu 27. Okt 2014 15:19

AW: TObjectList als Result
 
Da hier die Referenzen nicht in der Liste verwaltet werden, verwende ich bei sowas gern dynamische Arrays als Result.

Stevie 27. Okt 2014 17:25

AW: TObjectList als Result
 
Interface basierte Listen, boom! 8-)

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.

TiGü 27. Okt 2014 17:55

AW: TObjectList als Result
 
Früher gab es IInterfaceList bzw. IInterfaceListEx in der Classes-Unit.

Stevie 27. Okt 2014 18:38

AW: TObjectList als Result
 
Zitat:

Zitat von TiGü (Beitrag 1277585)
Früher gab es IInterfaceList bzw. IInterfaceListEx in der Classes-Unit.

Gibt es immer noch und das ist ein Interface, was Zugriff auf eine Liste von Interfaces gibt, wie der Name auch schon andeutet.

TiGü 28. Okt 2014 07:09

AW: TObjectList als Result
 
Zitat:

Zitat von Stevie (Beitrag 1277588)
Zitat:

Zitat von TiGü (Beitrag 1277585)
Früher gab es IInterfaceList bzw. IInterfaceListEx in der Classes-Unit.

Gibt es immer noch und das ist ein Interface, was Zugriff auf eine Liste von Interfaces gibt, wie der Name auch schon andeutet.

Was der von dir angesprochenden "TInterfacedObjectList" für ältere Delphis entspricht, richtig?

Sir Rufo 28. Okt 2014 09:18

AW: TObjectList als Result
 
Zitat:

Zitat von TiGü (Beitrag 1277634)
Zitat:

Zitat von Stevie (Beitrag 1277588)
Zitat:

Zitat von TiGü (Beitrag 1277585)
Früher gab es IInterfaceList bzw. IInterfaceListEx in der Classes-Unit.

Gibt es immer noch und das ist ein Interface, was Zugriff auf eine Liste von Interfaces gibt, wie der Name auch schon andeutet.

Was der von dir angesprochenden "TInterfacedObjectList" für ältere Delphis entspricht, richtig?

Falsch.

Eine Delphi-Referenz durchsuchenSystem.Classes.IInterfaceList ist für Items vom Typ
Delphi-Quellcode:
IInterface
.
Eine
Delphi-Quellcode:
TInterfacedObjectList
soll für Items vom Typ
Delphi-Quellcode:
TObject
sein.

TiGü 28. Okt 2014 10:16

AW: TObjectList als Result
 
Zitat:

Zitat von Sir Rufo (Beitrag 1277651)
Eine
Delphi-Quellcode:
TInterfacedObjectList
soll für Items vom Typ
Delphi-Quellcode:
TObject
sein.

Also eine normale, nicht-generische TObjectList?

Sir Rufo 28. Okt 2014 10:42

AW: TObjectList als Result
 
Zitat:

Zitat von TiGü (Beitrag 1277658)
Zitat:

Zitat von Sir Rufo (Beitrag 1277651)
Eine
Delphi-Quellcode:
TInterfacedObjectList
soll für Items vom Typ
Delphi-Quellcode:
TObject
sein.

Also eine normale, nicht-generische TObjectList?

Ähm, ja, so ist doch die Frage, darum geht es doch dem TE (der übrigens auch nur Delphi 7 hat, was soll der da mit Generics?)
Nur dass sich diese bekannte
Delphi-Quellcode:
TObjectList
als Rückgabewert einer Funktion etwas ungeschickt ist (wegen der evtl. zu erwartenden Speicherlecks). Darum der (gute) Vorschlag von Stevie statt einer
Delphi-Quellcode:
TObjectList
ein
Delphi-Quellcode:
Interface
zurückzugeben, was die gleichen Eigenschaften, wie
Delphi-Quellcode:
TObjectList
hat, sich aber (weil es ja ein
Delphi-Quellcode:
Interface
ist) von selber wieder aus dem Speicher entfernt, sobald da niemand mehr den Finger drauf hat.

Da hinter einem
Delphi-Quellcode:
Interface
immer (mindestens) eine konkrete Klasse steht war der Vorschlag diese Klasse einfach
Delphi-Quellcode:
TInterfacedObjectList
zu nennen.

TiGü 28. Okt 2014 10:59

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.

Sir Rufo 28. Okt 2014 11:02

AW: TObjectList als Result
 
Zitat:

Zitat von TiGü (Beitrag 1277666)
Zitat:

Zitat von Sir Rufo (Beitrag 1277662)
Ähm, ja, so ist doch die Frage, darum geht es doch dem TE (der übrigens auch nur Delphi 7 hat, was soll der da mit Generics?)

Eben!
Mir ist schleierhaft, was der TE mit der von Stevie vorgeschlagenen, selbst gebastelten "TInterfacedObjectList" anfangen soll?!

:roll:
Delphi-Quellcode:
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.
Und dann im seinem Quelltext
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;

TiGü 28. Okt 2014 11:04

AW: TObjectList als Result
 
Zitat:

Zitat von Sir Rufo (Beitrag 1277667)
:roll:

Siehe mein kurz zuvor getätigtes Edit!

DeddyH 28. Okt 2014 11:06

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.

Sir Rufo 28. Okt 2014 11:12

AW: TObjectList als Result
 
Zitat:

Zitat von DeddyH (Beitrag 1277671)
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.

Oh ja, da muss ich nochmal einen Manntag Arbeit reinstecken, damit das nicht passiert
Delphi-Quellcode:
Result := TInterfacedObjectList.Create( 
  {OwnsObjects} False );
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 :)

bernau 28. Okt 2014 11:17

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.

mkinzler 28. Okt 2014 11:20

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.

Sir Rufo 28. Okt 2014 11:21

AW: TObjectList als Result
 
@bernau

Die Lösung kam schon mit der ersten Antwort, und der Rest handelt von den Seiteneffekten (Speicherlecks).

bernau 28. Okt 2014 11:26

AW: TObjectList als Result
 
Zitat:

Zitat von Sir Rufo (Beitrag 1277677)
@bernau

Die Lösung kam schon mit der ersten Antwort, und der Rest handelt von den Seiteneffekten (Speicherlecks).

Deshalb werden Interfaces vorgeschlagen? Finde ich als Lösung für den TE sehr verwirrend. Ein Hinweis auf Mylist.Free genügt doch, wie er von "Neutral General" vorgeschlagen wurde.

bernau 28. Okt 2014 11:34

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.

Sir Rufo 28. Okt 2014 11:39

AW: TObjectList als Result
 
Zitat:

Zitat von bernau (Beitrag 1277679)
Zitat:

Zitat von Sir Rufo (Beitrag 1277677)
@bernau

Die Lösung kam schon mit der ersten Antwort, und der Rest handelt von den Seiteneffekten (Speicherlecks).

Deshalb werden Interfaces vorgeschlagen? Finde ich als Lösung für den TE sehr verwirrend. Ein Hinweis auf Mylist.Free genügt doch, wie er von "Neutral General" vorgeschlagen wurde.

Dafür werden/wurden auch Interfaces vorgeschlagen, ja völlig legitim. Entscheiden soll er selber, was ihm am Besten in den Kram passt.

Blup 28. Okt 2014 12:02

AW: TObjectList als Result
 
Viel Diskussion um das Thema, aber auf den zweiten Fehler ist niemand direkt eingegangen:
Zitat:

Zitat von Kuehter (Beitrag 1277533)
Delphi-Quellcode:
var
    MyList: TObjectlist;
    counter : integer;

begin

    Mylist := ImageLoader;
    Allrounder := TImage(Imageloader.Items[5]);
    Allrounder.Picture.LoadFromFile('Unbenannt.jpg');

end;

Wenn "ImageLoader" zwei mal aufgerufen wird, werden natürlich auch zwei Objektlisten erstellt.
Und die zweite kann man bei dieser Art des Aufrufs auch nicht mehr freigeben.
Delphi-Quellcode:
Mylist := ImageLoader;
try
  Allrounder := TImage(Mylist[5]);
finally
  MyList.Free;
end;
Abgesehen davon währe ein Property mit Index hier sinnvoller:
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;

bernau 28. Okt 2014 12:11

AW: TObjectList als Result
 
Zitat:

Zitat von Blup (Beitrag 1277690)
Viel Diskussion um das Thema, aber auf den zweiten Fehler ist niemand direkt eingegangen:

Dein Property ImageLoader ist genau richtig. Aber warum überhaut Allrounder verwenden?

dann direkt folgendes

Delphi-Quellcode:
begin
  ImageLoader[5].Picture.LoadFromFile('Unbenannt.jpg');
end;

bernau 28. Okt 2014 12:14

AW: TObjectList als Result
 
Aber noch mal. Der TE äussert sich nicht. Damit weis keiner, was wirklich gewollt ist.

DeddyH 28. Okt 2014 12:21

AW: TObjectList als Result
 
Zitat:

Zitat von Blup (Beitrag 1277690)
Viel Diskussion um das Thema, aber auf den zweiten Fehler ist niemand direkt eingegangen

Lies doch mal den von mir verlinkten Artikel ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:41 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