Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Welchen Sinn macht dieser Code? (https://www.delphipraxis.net/181629-welchen-sinn-macht-dieser-code.html)

Popov 30. Aug 2014 13:27

Welchen Sinn macht dieser Code?
 
Vielleicht liegt es daran, dass ich Formulare selten erst zur Laufzeit erzeuge oder weil ich noch nicht richtig wach bin, aber ich verstehe den tieferen Sinn des Beispiels nicht. Der ist vermutlich schon vorhanden.
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Form2 := TForm2.Create(Self);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(Application);
  Form2.ShowModal;
  Form2.Release;
end;
Form2 ist in Liste der verfügbaren Formulare. Zuerst stelle ich mir die Frage: warum? Wenn der Programmierer es sofort in Create von Form1 erzeugt, dann hätte man es auch direkt einbinden können. Um das Formular anzuzeigen braucht man nicht den Code in Button1Click, das würde auch so gehen. Einfach Form2.ShowModal.

Betrachten wir das anders, Form2 wird nur gelegentlich benötigt. Somit macht der Code in Button1Click Sinn, wozu dann aber der Part in FormCreate?

Und wenn wir schon dabei sind, wieso einmal TForm2.Create(Self) und einmal TForm2.Create(Application)?


//EDIT:

Was ich noch vergessen habe zu sagen: natürlich wird in FormCreate von Form2 etwas erledigt was für Form1 auch wichtig ist, aber kann es es sein dass der Programmierer einfach nur vergessen hat das Fenster danach wieder frei zu geben? Es also keinen tieferen Sinn macht?

himitsu 30. Aug 2014 13:47

AW: Welchen Sinn macht dieser Code?
 
Die Sache mit dem Owner hast du aber verstanden?

Create(Self) besagt, daß hier Form1 der Owner ist und wenn Form1 freigegeben wird, dann wird dvon auch Form2 freigegeben.
Ich hoffe nur, daß hier die Variable Form2 auch eine Private der Form1 ist und nicht die Globale. :evil:

Und beim Anderen ist die Application der Owner, womit das freigegeben würde, wenn die Anwendng beendet wird.
Rein formal wäre es hier aber auch besser das Self zu übegeben, da die Form2 dort ja nur aktiv ist, solange es Form1 gibt, bzw. nur solange der Button-Klick ausgeführt wird.
Womit man das auch eigentlich nil lassen könnte, da die Form ja manuell freigegeben wird und sich "eigentlich" kein anderer um die Freigabe kümmern müsste.

Da man dort aber den Resourcenschutzblock vergessen hat, kümmert sich dann die Applikation um die Freigabe, wenn es im ShowModal knallt (Exception), was schnell passiert, wenn z.B. TForm2.Visible=True ist.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Form2: TForm2;
begin
  Form2 := TForm2.Create(Application); // Hier eigentlich besser Self, da eine Methode Dieses ja das Ding erstellt und freigibt. Oder nil, da es manuell freigegeben wird und kein Owner nötig ist.
  try
    Form2.ShowModal;
  finally
    Form2.Release; // Das ist fast sowas wie Form2.Free; nur daß beim Free die Form sofort freigegeben wird und beim Release erst später, wenn das Programm Lust dazu hat.
  end;
end;
Und auch da ist wieder der Schrott mir der globalen Variable, denn die Form wird hier nur lokal erstellt und gleich wieder freigegeben.


PS: Man kann eine Form mehrfach erstellen und gleichzeitig anzeigen.
Und gerade deswegen waren auch die bösen Kommentare zu der globalen Form2-Variable.

Im TForm1.FormCreate wird deas Fenster einmal erstellt und in Button2.Click nochmal.
Wenn man jetzt noch die automatische Erstellung im Projekt aktiv lässt, dann gibt es diese Form 2 bis 3 Mal.

Wenn jetzt noch die globale Variable Form2 für alles verwendet wird, dann rate mal welche Form darin verlinkt ist und auf was man zugreift, wenn man diese benutzt.
Tipp: Nach dem Buttonklick, steht da schrott drin, nämlich die veraltete Referenz auf die Form von dort, welche es nicht mehr gibt.


Und dann noch das TForm2.Visible:
Wenn das auf False steht dann wird die Instanz aus FormCreate nicht angezeigt, da dort das Show, bzw. Visible:=True fehlt.
Und wenn das True ist, dann wird die Instanz aus FormCreate angezeigt, aber der Aufruf im Button1Click schlägt fehlt, denn eine sichtbare Form kann nicht Modal werden,
weswegen auch der Hinweis auf den Resourcenschutzblock war, da dann die Form nicht mehr freigegeben wird. (Release wird ja nicht mehr ausgeführt)

Sir Rufo 30. Aug 2014 14:05

AW: Welchen Sinn macht dieser Code?
 
Eigentlich ist es ganz einfach was da passiert:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  // Erzeugen einer Instanz und die Referenz wird in Form2 gespeichert
  Form2 := TForm2.Create(Self);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Erzeugen einer Instanz und die Referenz wird in Form2 gespeichert
  Form2 := TForm2.Create(Application);
  Form2.ShowModal;
  Form2.Release;
end;
Nachdem dem Aufruf von
Delphi-Quellcode:
TForm1.FormCreate
haben wir also eine Instanz-Referenz in
Delphi-Quellcode:
Form2
stehen.

Jetzt kommt der Aufruf von
Delphi-Quellcode:
TForm1.Button1Click
und es wird eine neue Instanz erzeugt, die Referenz in
Delphi-Quellcode:
Form2
gespeichert und am Ende wird die Instanz freigegeben.

Jeder Zugriff auf die Instan, deren Referenz in
Delphi-Quellcode:
Form2
steht, würde jetzt aber eine Zugriffsverletzung auslösen, denn diese Instanz wurde ja freigegeben.

Es dümpelt zwar irgendwo noch eine Instanz von
Delphi-Quellcode:
TForm2
herum, aber wir haben ja - vorsorglich - die Referenz darauf vergessen (dann kann die auch nicht kaputt gehen) ;)

Einen Memoryleak haben wir nicht, denn beim Beenden der Anwendung wird diese vergessene Instanz durch die Owner-Beziehung korrekt freigegeben.

Nein, Sinn macht das ganze nicht, es sei denn, man möchte einfach nur Speicher belegen.

EDIT:
Hier mal eine kleine Erweiterung
Delphi-Quellcode:
type
  TForm1 = class( TForm )
    Button1 : TButton;
    Button2 : TButton;
    procedure FormCreate( Sender : TObject );
    procedure Button1Click( Sender : TObject );
    procedure Button2Click( Sender : TObject );
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1 : TForm1;

implementation

{$R *.dfm}

uses
  Unit2;

procedure TForm1.Button1Click( Sender : TObject );
begin
  Form2 := TForm2.Create( Application );
  Form2.ShowModal;
  Form2.Release;
end;

procedure TForm1.Button2Click( Sender : TObject );
begin
  Form2.ShowModal;
end;

procedure TForm1.FormCreate( Sender : TObject );
begin
  Form2 := TForm2.Create( Self );
end;
Nach dem Start einfach mal auf den Button2 klicken und wunderbar, es funktioniert.
Jetzt auf Button1 (geht auch) und dann wieder auf Button2 -> Zugriffsverletzung (wie zu erwarten)

EDIT2:
Und korrekterweise sollte das dann so aussehen:
Delphi-Quellcode:
procedure TForm1.Button3Click( Sender : TObject );
var
  LForm : TForm2;
begin
  // wozu einen Owner, wenn wir es eh wieder freigeben wollen?
  // die Referenz in einer lokalen Variable speichern
  // try..finally um die Instanz gesichert wieder freizugeben
  LForm := TForm2.Create( nil );
  try
    LForm.ShowModal;
  finally
    LForm.Free;
  end;
end;

Popov 30. Aug 2014 14:20

AW: Welchen Sinn macht dieser Code?
 
Zitat:

Zitat von himitsu (Beitrag 1270301)
Die Sache mit dem Owner hast du aber verstanden?

Das eigentlich schon, nur hätte ich es nur anders gelöst. Was mich etwas verwirrt hat war, dass Form2 in FormCreate für einen Job erzeugt, dann aber nicht wieder freigegeben wird. Vor allem, weil es in Button1Click nach dem Job sofort immer freigegeben wird. Und dann weil Owner mal Self, mal Application ist. Ich dachte das hat einen speziellen Hintergrund.

Danke für die Erklärungen.

hoika 30. Aug 2014 15:07

AW: Welchen Sinn macht dieser Code?
 
Hallo,

kurz und knapp.
Der Code macht keinen Sinn.

Heiko

himitsu 30. Aug 2014 15:54

AW: Welchen Sinn macht dieser Code?
 
Zitat:

Zitat von hoika (Beitrag 1270307)
Der Code macht keinen Sinn.

Wenn die Form wirklich einmal dauerhaft und dann nocheinmal kurz für jeden Button-Klick vorhanden sein soll, dann wäre es schon "sinnvoll".

Aber dann nicht auf der selben Variable und mit ein paar weiteren Änderungen.

Popov 30. Aug 2014 16:12

AW: Welchen Sinn macht dieser Code?
 
Ok, ich hab mir den Code jetzt weiter angesehen. In FormCreate von Form2 steht nur eine Zeile mit einer Prozedur. In der Prozedur werden einige Daten von Form1 an Form2 übergeben. Form2 ist ein Optionsfenster. Somit ergibt die Zeile
Delphi-Quellcode:
Form2 := TForm2.Create(Self);
in FormCreate von Form1 sowieso keinen Sinn.

Das Ganze macht erst Sinn in Button1Click, da da auch Informationen von Form2 an Form1 zurück fließen.


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