Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   "FinalllyExit" gewünscht (https://www.delphipraxis.net/160164-finalllyexit-gewuenscht.html)

FredlFesl 30. Apr 2011 17:20

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von Stevie (Beitrag 1097882)
Ja, richtig, hier prallen wieder mal die unterschiedlichen Ansichtsweisen, was sauberer Code ist und was nicht, aufeinander. Ich stehe nach wie vor zu meiner Meinung und ich werde auch an irgendeiner Stelle wo es "nötig ist", von den 0.01% der Fälle Gebrauch machen und ein Exit einsetzen. Aber in keinem der hier im Thread erwähnten Fälle.


Du nimmst wirklich die 2.Variante? :shock:
Delphi-Quellcode:
// Total schlecht lesbarer und unsauberer Code mit EXIt
For i:=1 to N Do
  For j := 1 to M Do
  Begin
    If Bla[i,j].HasInvalidData() Then Exit;
    Bla[i,j].Process();
    ...
  End;
...
//
...
// Suupersaubere Implementierung ohne EXIT. Toll!
i := 1;
Aborted := False;
While (i <= N) and not Aborted Do
Begin
  j := 1;
  While (j <= M) and Not Aborted Do
  Begin
    If Bla[i,j].HasInvalidData() Then
      Aborted := True
    Else
    Begin
      Bla[i,j].Process();
      ...
      Inc(J)
    End;
  End;
  Inc(i);
End;

Stevie 30. Apr 2011 17:25

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von FredlFesl (Beitrag 1097929)
Du nimmst wirklich die 2.Variante? :shock:

Nein, ich lagere die innere Schleife in eine extra Methode aus, wenn es nicht so geht, wie ich im vorherigen Post erwähnte.

Namenloser 30. Apr 2011 17:32

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von Stevie (Beitrag 1097931)
Zitat:

Zitat von FredlFesl (Beitrag 1097929)
Du nimmst wirklich die 2.Variante? :shock:

Nein, ich lagere die innere Schleife in eine extra Methode aus, wenn es nicht so geht, wie ich im vorherigen Post erwähnte.

Dann brauchst du in der äußeren aber immer noch ein break oder ein Abort-Flag.

Stevie 30. Apr 2011 17:49

AW: "FinalllyExit" gewünscht
 
Break schlechter Programmierstil?

Wobei ich Break ehrlich gesagt öfter einsetze

himitsu 30. Apr 2011 18:21

AW: "FinalllyExit" gewünscht
 
Im Prinzip sind das alles die selben Funktionalitäten
> "Abbrechen" aka unterbrechen des linearen Programmablaufs

If/Case > überspringen von Befehlen
Continue > einen Schleifendurchgang abbrechen
Break > ganze Schleife abbrechen
Exit > Funktion verlassen
Raise (Exception) > Thread beenden (es sei denn die Exception wird abgefangen > Try-Except)
Halt > Programm sofort beenden (ist voll unsauber und eher für schwerwiegende Poblembehandlungen geeignet)

(Goto könnte man bei mehreren dieser Punkte dazuschreiben)

Stevie 30. Apr 2011 18:38

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von himitsu (Beitrag 1097937)
Im Prinzip sind das alles die selben Funktionalitäten
> "Abbrechen" aka unterbrechen des linearen Programmablaufs

If/Case > überspringen von Befehlen
Continue > einen Schleifendurchgang abbrechen
Break > ganze Schleife abbrechen
Exit > Funktion verlassen
Raise (Exception) > Thread beenden (es sei denn die Exception wird abgefangen > Try-Except)
Halt > Programm sofort beenden (ist voll unsauber und eher für schwerwiegende Poblembehandlungen geeignet)

(Goto könnte man bei mehreren dieser Punkte dazuschreiben)

Und? Nur weils es gibt, isses auch gut?

Und nur, um es nochmal zu betonen, ich sage nicht, man darf das auf keinen Fall niemalsnich verwenden. Aber bereits das Code Beispiel im TE Post zeigte, dass dort Exit mal total falsch plaziert war. Man sollte die Verwendung auf ein absolutes Minumum reduzieren und nicht dort, wo man einfach nur nen Boolschen Ausdruck negieren könnte, nen Exit reindonnern.

Aphton 30. Apr 2011 18:40

AW: "FinalllyExit" gewünscht
 
Die Existenz derer sagt, so wie du es schon angedeutet hast, nichts über ihr Nutzen (nützlich, gut, böse?) aus.
Es liegt alles am Programmierer.

Eigentlich sind wir hier alle in eine Tangente abgedriftet. Wäre nett, wenn man die Diskussion fortsetzen will, nen neuen Thread zu eröffnen!

stahli 19. Mai 2011 23:07

AW: "FinalllyExit" gewünscht
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:

Zitat von NamenLozer (Beitrag 1101760)
(anderer Thread)
Zitat:

Zitat von stahli (Beitrag 1101758)
- FinallyExit (fände ich trotz allem besser als das try-finally-Gewurschtel :wink:)

Ich glaube damit stehst du ziemlich allein. Warum sollte man das exakt selbe Feature doppelt implementieren? Bei den restlichen Punkten stimme ich dir aber weitestgehend zu.

Ich habe mal ein Testprojekt angehängt.
An den try-Blöcken stört mich die schlechte Debugbarkeit. Gerade habe ich einen Fehler gefunden, der in einer aufgerufenen Funktion auftrat. Durch den sch... try-Block war der schlechter lokalisierbar.
Ich mag die Dinger nicht und halte sie für wesentlich überschätzt.
Wenn man sie konsequent nutzen will, müsste man quasi jeden Befehl in einen try-Block kapseln.
Delphi-Quellcode:
A:=TA.Create;
B:=TB.Create;
try
  ...
finally
  A.Free;
  B.Free;
end;
Was aber, wenn schon TA.Create fehl schlägt???
Also müsste man dutzende try-Blöcke ineinander schachteln, um wirklich sicher zu sein?
Ich halte das für Unsinn.

In meinem Testprojekt kann man sehen, dass "end(normal)" nur in einem Fall aufgerufen wird.
Was ist aber bei 2 verschachtelten oder aufeinander folgenden try-Blöcken?

Ich halte ein Standardlabel "FinallyExit" für sehr sinnvoll, das einfach IMMER vor dem Verlassen einer Funktion/Prozedur angesprungen wird, egal was vorher auch immer passiert ist.
Sehr schwierig sollte das nicht lösbar sein, da ja weitestgehend nur die Exit-Sprungadresse geändert werden müsste.

PS: Das mit einem selbst definierten Label zu testen, wäre etwas umständlich, da man Exit(VALUE) so nicht (mit einer Anweisung) simulieren kann.


Delphi-Quellcode:
unit fTestFinallyExit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TFormTestFinallyExit = class(TForm)
    ButtonTest: TButton;
    Memo: TMemo;
    RadioGroupMode: TRadioGroup;
    procedure RadioGroupModeClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    function Test: String;
  end;

var
  FormTestFinallyExit: TFormTestFinallyExit;

implementation

{$R *.dfm}

procedure TFormTestFinallyExit.RadioGroupModeClick(Sender: TObject);
begin
  Memo.Lines.Add('-----' + RadioGroupMode.Items[RadioGroupMode.ItemIndex] + '-----');
  Memo.Lines.Add(Test);
  Memo.Lines.Add('');
end;

function TFormTestFinallyExit.Test: String;
var
  S: String;
  I: Integer;

  procedure Add(SA: String);
  begin
    S := S + SA + #13#10;
  end;

begin
  Result := 'nix';
  S := '';
  I := 0;
  Add('begin');
  if RadioGroupMode.ItemIndex = 1 then
  begin
    Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
    Exit;
  end;
  if RadioGroupMode.ItemIndex = 2 then
  begin
    Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
    Exit('#');
  end;
  if RadioGroupMode.ItemIndex = 3 then
  begin
    Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
    Add(IntToStr(1 div I));
  end;
  try
    Add(' try');
    if RadioGroupMode.ItemIndex = 4 then
    begin
      Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
      Exit;
    end;
    if RadioGroupMode.ItemIndex = 5 then
    begin
      Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
      Exit('   #');
    end;
    if RadioGroupMode.ItemIndex = 6 then
    begin
      Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
      Add(IntToStr(1 div I)); // springt in finally und dann Exit ohne Result-Zuweisung
    end;
    Add('   ok');
  finally
    Add(' finally');
    Add('end(finally)');
    Result := S;
  end;
  Add('end(normal)');
  Result := S;
end;

end.

omata 19. Mai 2011 23:20

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von stahli (Beitrag 1101885)
Ich halte ein Standardlabel "FinallyExit" für sehr sinnvoll, das einfach IMMER vor dem Verlassen einer Funktion/Prozedur angesprungen wird, egal was vorher auch immer passiert ist.
Sehr schwierig sollte das nicht lösbar sein

Stimmt! Das ist überhaupt nicht schwer und muss auch nicht realisiert werden, weil es das gibt.

Delphi-Quellcode:
begin
  try
    // hier kommt alles rein
  finally
    // und das hier wird vor dem Verlassen ausgeführt, egal, was vorher war.
  end;
end;
Also worum gehts hier eigentlich. Alles da, was man braucht. Und deine tolle Idee ist nichts anderes und hat dann auch die selben Nachteile, die du hier vielleicht aufführen wirst.

Dabei gibt es gar keine Nachteile.

Namenloser 19. Mai 2011 23:26

AW: "FinalllyExit" gewünscht
 
Ich sehe einfach nicht was der Vorteil von deinem FinallyExit sein soll. Was ist der Unterschied, ob ich schreibe
Delphi-Quellcode:
procedure Foobar;
begin
  try
    {&#8230;}
    if foo=bar then
      Exit;
    {&#8230;}
  finally
    ShowMessage('foobar end')
  end;
end;
oder
Delphi-Quellcode:
procedure Foobar;
begin
  {&#8230;}
  if foo=bar then
    Exit;
  {&#8230;}
  FinallyExit:
    ShowMessage('foobar end')
end;
?
Der einzige Unterschied, den ich sehe, ist, dass in letzterem Fall eine Zeile und eine Verschachtelung spare; aber dafür kommt ein zusätzliches, redundantes Sprachfeature hinzu.

Zitat:

Zitat von stahli (Beitrag 1101885)
Ich mag die Dinger nicht und halte sie für wesentlich überschätzt.
Wenn man sie konsequent nutzen will, müsste man quasi jeden Befehl in einen try-Block kapseln.
Delphi-Quellcode:
A:=TA.Create;
B:=TB.Create;
try
  ...
finally
  A.Free;
  B.Free;
end;
Was aber, wenn schon TA.Create fehl schlägt???
Also müsste man dutzende try-Blöcke ineinander schachteln, um wirklich sicher zu sein?
Ich halte das für Unsinn.

Dafür gibt es ein schönes Pattern:
Delphi-Quellcode:
A := nil;
B := nil;
try
  A := TA.Create;
  B := TB.Create;
finally
  A.Free;
  B.Free;
end;
Das Tolle an Free ist nämlich, dass erst geprüft wird, ob self nil ist:
Delphi-Quellcode:
procedure TObject.Free;
begin
  if Assigned(self) then
    Destroy;
end;
Abgesehen davon löst dein FinallyExit das von dir angesprochene Problem auch nicht.

Bezüglich deines Codebeispiels:
Wieso nicht einfach so?
Delphi-Quellcode:
function TFormTestFinallyExit.Test: String;
{&#8230;}
begin
  Result := 'nix';
  S := '';
  I := 0;
  Add('begin');
  {&#8230;}
  try
    Add(' try');
    {&#8230;}
    if RadioGroupMode.ItemIndex = 6 then
    begin
      Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
      Add(IntToStr(1 div I));
    end;
    Add(' ok');
  finally
    Add(' finally');
    Add('end(finally)');
    Result := S; // redundant
    Add('end(normal)');
    Result := S;
  end;
end;
oder so:
Delphi-Quellcode:
function TFormTestFinallyExit.Test: String;
{&#8230;}
begin
  try
    Result := 'nix';
    S := '';
    I := 0;
    Add('begin');
    {&#8230;}
    try
      Add(' try');
      {&#8230;}
      if RadioGroupMode.ItemIndex = 6 then
      begin
        Add(RadioGroupMode.Items[RadioGroupMode.ItemIndex]);
        Add(IntToStr(1 div I));
      end;
      Add(' ok');
    finally
      Add(' finally');
      Add('end(finally)');
      Result := S; // redundant
    end;
  finally
    Add('end(normal)');
    Result := S;
  end;
end;

stahli 19. Mai 2011 23:38

AW: "FinalllyExit" gewünscht
 
@Omata
Sofern nur ein Try-Block existiert stimmt das (habe ich ja in meinem Projekt jetzt auch so genutzt).
Aber die Struktur ist unschön, sofern in FuncA ein Fehler auftritt. Dieser ist schwerer zu finden, als wenn es keinen Try-Block gäbe.

Delphi-Quellcode:
begin
  try
    FuncA;
    FuncB;
    // hier kommt alles rein
  finally
    // Bei Fehler in FuncA geht es kommentarlos hier weiter.
    // und das hier wird vor dem Verlassen ausgeführt, egal, was vorher war.
  end;
end;
@NamenLozer
Naja, man könnte sich die Verschachtelungen sparen.
Und ein Try-Block ist ja nicht dafür da, einen Funktionsaussprung zu regeln, sondern Fehler abzufangen.
Das ist aber nicht mein Anliegen.

Man könnte sich ja auch eine abschließende Ergebnisberechnung vorstellen, z.B.
Delphi-Quellcode:
Result := A+B+C
, die an 10 verschiedenen Stellen notwendig werden kann.
Mit FinallyExit bräuchte man dies nur als letzte Zeile deklarieren und könnte überall einfach Exit aufrufen, das den Resultwert berechnet und den Rücksprung veranlasst.
Ich fände das übersichtlich und logisch.


@all
Aber ok, ich gebe mich geschlagen. :?

omata 19. Mai 2011 23:42

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von stahli (Beitrag 1101891)
Aber die Struktur ist unschön, sofern in FuncA ein Fehler auftritt. Dieser ist schwerer zu finden, als wenn es keinen Try-Block gäbe.

Das verstehe ich nicht. Delphi hat so einen guten Debugger, da kann doch Zeile für Zeile sehr gut überprüft werden. Vor jedem Debug-Step muss man selbst überlegen, was als nächstes passiert. Da ist nichts unübersichtlich. Sorry, ich verstehe es nicht.

stahli 19. Mai 2011 23:50

AW: "FinalllyExit" gewünscht
 
Ohne den Try-Block in der übergeordneten Methode hätte es SOFORT eine schöne Fehlermeldung in der Funktion gegeben.
Durch den Try-Block wurde die unterdrückt. Ich habe den Fehler ja letztlich gefunden aber ich bin immer noch der Meinung, dass try nur bei "ERWARTETEN FEHLERN" Sinn macht (z.B. E/A-Fehler), auf die dann reagiert werden muss.

Was nutzt es mir, wenn 2 Objekte freigegeben werden, aber der eigentliche Methodenzweck fehl geschlagen ist.
Except macht ja u.U. Sinn, aber finally (ohne Fehlerbehandlung)?

Aber ich wiederhole mich. Soll also genug sein.

omata 19. Mai 2011 23:57

AW: "FinalllyExit" gewünscht
 
Mir fehlen da einfach die Worte, wenn ich das lese. Aber für dich gibt es doch eine ganz einfache Lösung: Verwende Try-Finally einfach nicht, dann ist deine Welt doch in Ordnung. Für den Rest gibt es halt dieses Konstrukt und diese Personen können das dann verwenden. Dann sind doch alle glücklich.

himitsu 20. Mai 2011 00:00

AW: "FinalllyExit" gewünscht
 
Finally unterdrückt keine Exceptions,
denn am Ende des Finally-Blocks wir die Exception automatisch wieder ausgelöst.
(es sei denn es tritt in Finally eine Anderere/Neue Exception auf, dann wird diese weitergereicht)



Zitat:

Delphi-Quellcode:
procedure xyz;
begin
  A := TA.Create;
  B := TB.Create;
  try
    ...
  finally
    A.Free;
    B.Free;
  end;
end;

Ist unsicher, wie richtig gesagt wurde, denn A wird nicht freigegeben, wenn es in TB.Create knallt.

Delphi-Quellcode:
procedure xyz;
begin
  A := TA.Create;
  B := TB.Create;
  ...
  FinallyExit:
  A.Free;
  B.Free;
end;
Ist nicht viel besser, denn A und B wurden nicht initialisiert und wenn es in einem der Konstruktoren knallt. dann nallt es auch bei den uninitialisierten Free's.
Außerdem übersieht man das FinallyExit schnell mal ... so erkennt man nicht, daß es da einen Schutzblock gibt und man sieht nicht wo der Block aufhört.

Delphi-Quellcode:
procedure xyz;
begin
  A := TA.Create;
  try
    B := TB.Create;
    try
      ...
    finally
      B.Free;
    end;
  finally
    A.Free;
  end;
end;

// oder
procedure xyz;
begin
  A := nil;
  B := nil;
  try
    A := TA.Create;
    B := TB.Create;
    ...
  finally
    A.Free;
    B.Free;
  end;
end;

// oder

procedure xyz;
begin
  B := nil;
  A := TA.Create;
  try
    B := TB.reate;
    ...
  finally
    A.Free;
    B.Free;
  end;
end;
so sieht es schon besser aus

Namenloser 20. Mai 2011 00:04

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von stahli (Beitrag 1101891)
Und ein Try-Block ist ja nicht dafür da, einen Funktionsaussprung zu regeln, sondern Fehler abzufangen.

Sagt wer? Try-Except ist zum Abfangen von Fehlern, ja, Try-Finally nicht unbedingt. Man verwendet Try-Finally zwar oft dazu, Ressourcen garantiert (auch im Falle eines Fehlers) wieder freizugeben, aber wie man sieht gibt es nicht nur diesen Anwendungsfall. Im Grunde heißt Try-Finally nur, dass ein bestimmter Code versuchsweise ausgeführt werden soll, und anschließend garantiert ein bestimmter anderer Code.

stahli 20. Mai 2011 00:14

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von himitsu (Beitrag 1101896)
Delphi-Quellcode:
procedure xyz;
begin
  A := TA.Create;
  B := TB.Create;
  ...
  FinallyExit:
  A.Free;
  B.Free;
end;

Es käme mir dabei eben nicht darauf an, wenn es "knallt". Gegeben sei eine tadellos funktionierende Funktion.
Deine 3 Punkte bearbeiten jede Menge Fallunterscheidungen, komplexe Verschachtelungen, Funktionsaufrufe usw.
An unterschiedlichen Stellen kann Exit aufgerufen werden und final noch etwas erledigt werden.
Das Ganze hat NICHTS mit Versuchen oder Fehlern zu tun. Es gibt diverse Abläufe und diverse Aussprünge.

Wie Eingangs schon diskutiert, kann man mit jeder Menge if..begin...end..else.. und temporären Flags arbeiten, ggf. auch mit Goto (wenn es nicht gleich wieder Aufschreie gibt).
Das sehr komfortable Exit(Value) lässt sich aber damit nicht nutzen.

Aber ok, wir kommen nicht zusammen. Dann lassen wir es einfach. Es war aber eine Weltidee. :-D

Namenloser 20. Mai 2011 00:17

AW: "FinalllyExit" gewünscht
 
@stahli: Aber genau was du beschreibst, das macht doch try-finally. Verabschiede dich doch mal von dem Gedanken, dass try-finally immer was mit Fehlern zu tun hat.
Delphi-Quellcode:
procedure xyz;
begin
  A := TA.Create;
  B := TB.Create;
  ...
  FinallyExit:
  A.Free;
  B.Free;
end;
ist 100% äquivalent zu
Delphi-Quellcode:
procedure xyz;
begin
  try
    A := TA.Create;
    B := TB.Create;
    ...
  finally
    A.Free;
    B.Free;
  end;
end;
(auch wenn das so, wie bereits gesagt, wenig sinnvoll ist)

omata 20. Mai 2011 00:18

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von stahli (Beitrag 1101899)
Es war aber eine Weltidee. :-D

Ja, à la Dittsche :hi:

FredlFesl 20. Mai 2011 06:45

AW: "FinalllyExit" gewünscht
 
Ein Konstruktor sollte doch niemals eine Exception werfen. Und wenn, braucht man das Objekt nicht freizugeben, weil die Konstruktorlogik den Speicher selbst wieder freigibt, bevor sie die Exception erneut schmeisst.

Try...Finally ergibt auch nur dann Sinn, wenn die Exception in einem der Aufrufer abgefangen und behandelt wird. Wenn ich beispielsweise irgendeine Verbindung 'öffne' und dann etwas mit ihr anstelle, möchte ich, das die Verbindung garantiert wieder geschlossen wird, bevor eine Stufe höher die Exception behandelt wird.

In C# gibt es übrigens etwas Ähnliches, nämlich das 'Using' - Konstrukt.

Zitat:

Zitat von NamenLozer (Beitrag 1101897)
Im Grunde heißt Try-Finally nur, dass ein bestimmter Code versuchsweise ausgeführt werden soll, und anschließend garantiert ein bestimmter anderer Code

Stimmt nicht ganz (also, das 'versuchsweise'). Dann würde 'Exit' nicht in den 'Finally'-Block springen. das 'garantiert' ist das Wesentliche.

Zitat:

Zitat von stahli (Beitrag 1101899)
Es käme mir dabei eben nicht darauf an, wenn es "knallt".

...Ahh. Geht mit 'try...finally'
Zitat:

Zitat von stahli (Beitrag 1101899)
An unterschiedlichen Stellen kann Exit aufgerufen werden und final noch etwas erledigt werden.

...Ahh. Geht mit 'try...finally'
Zitat:

Zitat von stahli (Beitrag 1101899)
Wie Eingangs schon diskutiert, kann man mit jeder Menge if..begin...end..else.. und temporären Flags arbeiten, ggf. auch mit Goto (wenn es nicht gleich wieder Aufschreie gibt).

Uaaaaarghl! (zufrieden? ;-) ) Deshalb wurde doch gerade try..finally erfunden
Zitat:

Zitat von stahli (Beitrag 1101899)
Das sehr komfortable Exit(Value) lässt sich aber damit nicht nutzen.

Weswegen man eben mit try..finally arbeitet.


Dein 'FinallyExit' widerspricht dem Gedanken der blockorientierten Programmiersprache und schränkt den Programmierer unnötig ein.
Beispiel:
...
Delphi-Quellcode:
FuncA();
Try
  FuncB();
Finally
  CleanupFuncBCallAndDefinetlyNotTheFuncACall();
End;
Wie willst Du das mit deinem 'FinallyExit' modellieren? Beachte, das FuncA außerhalb des Try..Finally steht und dieser Aufruf nicht aufgeräumt werden soll, wenn er schiefgeht.

himitsu 20. Mai 2011 07:42

AW: "FinalllyExit" gewünscht
 
Zitat:

versuchsweise ausführen
Logiksteuerung via Exceptions ist in der Regel eh verpöhnt.

Try-Finally/Except ist für den "Notfall" ... Exception = Ausnahme

Zitat:

Zitat von FredlFesl (Beitrag 1101911)
Ein Konstruktor sollte doch niemals eine Exception werfen. Und wenn, braucht man das Objekt nicht freizugeben, weil die Konstruktorlogik den Speicher selbst wieder freigibt, bevor sie die Exception erneut schmeisst.

Das stimmt schon, aber
Delphi-Quellcode:
A := TA.Create;
B := TB.Create;
try
Knallt es hier im B, dann gibt sich B selber wieder frei .... nur um das A kümmert sich keiner mehr.

PS: Ja, beim Erstellen und wärend der Bearbeitung sind A und B hier abgesichert, aber
Delphi-Quellcode:
finally
  A.Free;
  B.Free;
end;
Knallt es jetzt im A.Free, dann wird B nicht freigegeben.
Der einzige Grund, warum diese Vereinfachung "oft" Funktional ist, liegt darin begründet, daß das Free oftmals "weniger" Probleme bereitet.
Ist das nicht sichergestellt, dann kommt man um verschachtelte Try-Finally nicht drumrum.
Es sei denn man weiß, daß z.B. A.Free (nahezu) niemals Exceptions werfen kann, dann ist auch B.Free mit großer Sicherheit noch geschützt.

Ich selber nutze eine derartige Kombination vorallem dann, wenn ich eben weiß, daß A.Free problemlos abläuft und für den Fall, daß es da doch mal knallt, dann ist der Programmablauf eh dermaßen gestört, daß das Programm beendet werden muß und sich keine weitere Absicherung mehr lohnt.

Und ja, an Stellen wo sich keine Fehlerbehandlung "lohnt", weil dann eh nix mehr geht, dann erspare ich mir auch schonmal eine Exceptionbehandlung, wie Try-Finally und selbst Speicherfreigaben werden schonmal einfach weggelassen. (weil dadurch der Programmcode schonmal übersichtlicher/kürzer werden kann, ohne das es probleme gibt, da ich weiß das sich Windows am Programmende auch um vieles nochmal kümmert ... das war vor der NT-Reihe noch wesentlich aufwändiger/wichtiger)

stahli 20. Mai 2011 09:04

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von himitsu (Beitrag 1101916)
Der einzige Grund, warum diese Vereinfachung "oft" Funktional ist, liegt darin begründet, daß das Free oftmals "weniger" Probleme bereitet.
Ist das nicht sichergestellt, dann kommt man um verschachtelte Try-Finally nicht drumrum.
Es sei denn man weiß, daß z.B. A.Free (nahezu) niemals Exceptions werfen kann, dann ist auch B.Free mit großer Sicherheit noch geschützt.

Ich selber nutze eine derartige Kombination vorallem dann, wenn ich eben weiß, daß A.Free problemlos abläuft und für den Fall, daß es da doch mal knallt, dann ist der Programmablauf eh dermaßen gestört, daß das Programm beendet werden muß und sich keine weitere Absicherung mehr lohnt.

Und ja, an Stellen wo sich keine Fehlerbehandlung "lohnt", weil dann eh nix mehr geht, dann erspare ich mir auch schonmal eine Exceptionbehandlung, wie Try-Finally und selbst Speicherfreigaben werden schonmal einfach weggelassen. (weil dadurch der Programmcode schonmal übersichtlicher/kürzer werden kann, ohne das es probleme gibt, da ich weiß das sich Windows am Programmende auch um vieles nochmal kümmert ... das war vor der NT-Reihe noch wesentlich aufwändiger/wichtiger)

:thumb: Genau so sehe ich das auch - aber eben auch für eine gesamte Methode. Wenn ich diese ausgiebig getestet habe und sicher bin, dass alles korrekt funktioniert (außer, wenn vielleicht der Hauptspeicher defekt ist o.ä.) dann kann ich auf solche Absicherungen auch verzichten, die eben aus meiner Sicht auch nur einen begrenzten Nutzen haben. Das Programm funktioniert ohnehin nicht mehr korrekt und der Fehler muss gefunden und beseitigt werden.

FredlFesl 20. Mai 2011 18:20

AW: "FinalllyExit" gewünscht
 
[QUOTE=himitsu;1101916]
Zitat:

PS: Ja, beim Erstellen und wärend der Bearbeitung sind A und B hier abgesichert, aber
Delphi-Quellcode:
finally
  A.Free;
  B.Free;
end;
Knallt es jetzt im A.Free, dann wird B nicht freigegeben.
Jo, sowas ist ja auch extrem unsauber, gelle?
Zitat:

Es sei denn man weiß, daß z.B. A.Free (nahezu) niemals Exceptions werfen kann, dann ist auch B.Free mit großer Sicherheit noch geschützt.
Wenn es im Destruktor knallt, ist's doch eh zu spät. Dann benötigt die Schädelvorderseite eine intensive Holzbrettbehandlung.

Sunlight7 21. Mai 2011 11:39

AW: "FinalllyExit" gewünscht
 
Zitat:

Zitat von jfheins (Beitrag 1097822)
Falls du das nicht glaubst, zeige bitte ein Stück Code wo das finally nicht ausgeführt wird ;)

Code:
try
   Halt;
finally
   Beep;
end;
:lol:

himitsu 21. Mai 2011 11:45

AW: "FinalllyExit" gewünscht
 
Halt ist eine Ausnahme, denn dieses "schießt" das Programm direkt ab, genau da wo es ist,
das ist praktisch das selbe Ergebnis, als wenn man die Anwendung im Taskmanager abschießt.

Darum sollte man auch möglichst darauf verzichten.

Stevie 21. Mai 2011 14:24

AW: "FinalllyExit" gewünscht
 
Ihr verlagert das Problem nur noch.... wenn im Konstruktor oder Destruktor eine Exception auftritt... Welche Art Exception? Programmierfehler? Sollte dann das Programm dafür sorgen, dass der ausgebügelt wird oder still und heimlich trotzdem weiterlaufen? Oder sollte man, wenn es zu erwarten ist, dass ein Fehler auftreten kann (z.b. man versucht eine Datei zu öffnen), nicht innerhalb der Methode mit try except arbeiten und somit letztlich sichergehen, dass der Aufruf des Konstruktors fehlerfrei abläuft? Ehrlich, wenn ich bei jedem Create und Free dafür sorgen müsste, dass ich mögliche Exceptions abhandle, hätt ich mich schon erhängt. Übrigens gibt's auch sowas, wie Unittests...


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:20 Uhr.
Seite 2 von 2     12   

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