Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi try .. except .. finally (https://www.delphipraxis.net/137104-try-except-finally.html)

Surrounder 14. Jul 2009 15:23


try .. except .. finally
 
Warum kann ich eigentlich wenn ich einen try benutze nicht einen except und ein finally verwenden?

Ich schreibe in eine Datei die auch schreibgeschützt sein kann, und dann kommt es zu einem Fehler. Ich würde gerne wenn es zu dieser Exception kommt eine Meldung in mein Logfile schreiben, aber dann trotzdem im finally das File wieder schließen.

Momentan gehe ich einfach her und mache zwei try hintereinandern, mich würde nur interessieren ob mir jemand sagen kann warum try .. except .. finally als ganzes nicht geht?!?

Delphi-Quellcode:

var
   ppFile : TNativeXML;
   node : TXMLNode;
begin
   try
      try

         ppFile := TNativeXml.CreateName('xyz');

         node := ppFile.Root.NodeNew( 'test123' );
         with node do begin
            WriteString( 'x', x);
            WriteInteger( 'y', y);

         end;

      except
         AddLogAlert( 'Fehler' );
      end;
   finally
      ppFile.Free;
   end;
end;

Stormy 14. Jul 2009 15:28

Re: try .. except .. finally
 
Ist so weil darum könnte man jetzt einfach sagen. Sind eben zwei uterschiedliche Befehle. Da müsstest du dich auch fragen warm man bei Case nicht auch of und in gleichzeitig benutzen kann.


Gruß
Stormy

MStoll 14. Jul 2009 15:41

Re: try .. except .. finally
 
Hi,

stelle dir einfach die Frage: wofür brauchst du den finally-Block, wenn du ein try...except unmittelbar davor hast?
Dadurch, dass alles davor abgefangen ist, wird das, was nach dem try...except-Block kommt, auf (fast) jeden Fall ausgeführt. Einzige Ausnahme: du hast im except-Teil wieder eine Exception.

Gruß
Michael

[Edit]Zumal: deine Verwendung der try-Blöcke ist nicht ganz im Sinne des Erfinders: was passiert denn, wenn's bei ppFile := TNativeXml.CreateName('xyz') zu einer Exception kommt?[/Edit]

Surrounder 14. Jul 2009 15:45

Re: try .. except .. finally
 
Zitat:

Zitat von MStoll
Hi,

stelle dir einfach die Frage: wofür brauchst du den finally-Block, wenn du ein try...except unmittelbar davor hast?
Dadurch, dass alles davor abgefangen ist, wird das, was nach dem try...except-Block kommt, auf (fast) jeden Fall ausgeführt. Einzige Ausnahme: du hast im except-Teil wieder eine Exception.

Gruß
Michael

Und für welchen Fall brauche ich dann überhaupt try .. finally?

Regan 14. Jul 2009 15:48

Re: try .. except .. finally
 
Zitat:

Zitat von Surrounder
Und für welchen Fall brauche ich dann überhaupt try .. finally?

Damit etwas auf jeden Fall passiert. In deinem Fall zum Beispiel müssen die Variablen freigegeben werden. Für eine StringList sieht sowas dann ungefähr so aus:
Delphi-Quellcode:
begin
  MySringList := TStringList.Create();
  try
    //hier käme dann anderer Code
  finally
    MyStringList.Free();
  end;
end;
So kannst du sicher gehen, dass auf jeden Fall der Speicher freigegeben wird, egal, was passiert.

Edit1: Kosmetik.
Edit2:

Das except ist im Endeffekt nur für Fehler, die du nicht selber abfangen kannst (z. B. bei falschen Rückmeldungen durch Server etc.). Gegen andere Dinge (Datei existiert, Datei zu groß/zu klein/nicht gültig) kannst du dich schützen.

angos 14. Jul 2009 15:49

Re: try .. except .. finally
 
Hi,

So herum ist es richtig.
Delphi-Quellcode:
[...]
begin
   ppFile := TNativeXml.CreateName('xyz');
   try
      try
         [...]
      except
         AddLogAlert( 'Fehler' );
      end;
   finally
      ppFile.Free;
   end;
end;
Ich frage mich allerdings noch immer, wozu du try except finally zusammen in einem Block brauchst. Nacheinander wird es doch sauber ausgeführt. Sehe da kein Problem. Das finally sollte in dem obigen Beispiel in jedem Fall ausgeführt werden.

Edit: nur nochmal um es als Info zusammenzufassen:

- finally dient dazu, einen Code in jedem Fall durchzuführen, zB zum Freigeben von Objekten
- except dient dazu, Fehler abzufangen und zu verarbeiten


Gruß
Ansgar

Surrounder 14. Jul 2009 15:51

Re: try .. except .. finally
 
Zitat:

Zitat von angos
Hi,

So herum ist es richtig.

Gruß
Ansgar

Dass es so richtig ist weiss ich, es funktionier ja auch. Ich wollte ja wissen warum es nicht wie folgt geht:

Delphi-Quellcode:
begin
   ppFile := TNativeXml.CreateName('xyz');
   try
         [...]
   except
         AddLogAlert( 'Fehler' );
   finally
      ppFile.Free;
   end;
end;

angos 14. Jul 2009 15:52

Re: try .. except .. finally
 
kurz und knapp: Nein. Ich sehe aber auch keinen sinn darin...außer dich drei buchstaben zu sparen ;)

edit: in deinem Code oben hattest du die Erstellung des Objektes nach dem ersten try durchgeführt. Ist imho nicht ganz sauber, das sollte schon vor dem ersten "try" erzeugt werden. Nur darauf wollte ich mit meinem Codeschnipsel hinweisen :)

Surrounder 14. Jul 2009 16:00

Re: try .. except .. finally
 
Zitat:

Zitat von angos
kurz und knapp: Nein. Ich sehe aber auch keinen sinn darin...außer dich drei buchstaben zu sparen ;)

edit: in deinem Code oben hattest du die Erstellung des Objektes nach dem ersten try durchgeführt. Ist imho nicht ganz sauber, das sollte schon vor dem ersten "try" erzeugt werden. Nur darauf wollte ich mit meinem Codeschnipsel hinweisen :)

Ah ok, das ist weil ich das als Beispiel schnell für das Post zusammenkopiert habe :oops:

Naja der Sinn darin wäre dass wenn ich z.B. beim schreiben in die Datei eine exception bekomme diese abfangen kann bzw. eine klare Fehlermeldung dazu ausgeben und ins logifle schreiben kann. Trotzdem will ich wenn die Exception kommt dass die Datei / Stringlist oder was auch immer definitive geschlossen wird. Das schließen soll aber natürlich auch wenn keine Exception kommt passieren (was ich normal im finally mache).

Aber es ist ok, ich kann damit leben dass ich drei Zeichen mehr tippen muss :balloon:

Muetze1 14. Jul 2009 16:04

Re: try .. except .. finally
 
Zitat:

Zitat von angos
So herum ist es richtig.

Wieso sollte? Wer sagt dir das?

Ich kann Exception des gesamten Blockes auch noch später abfangen, also warum sollte es nun richtig sein den Except Block innerhalb des Finallys zu haben? Bitte gebe mir mindestens eine schlüssige Begründung dazu.

Und wo wir gerade dabei sind an alle Leser nochmal ein Hinweis über einen gerne gemacht Fehler in diesem Zusammenhang:

Delphi-Quellcode:
var
  lFile: TNativeXML;
begin
   try
     lFile := TNativeXml.CreateName('xyz');
     [...]
   finally
      FreeAndNil(lFile);
   end;
end;
In dieser Konstellation gibt Delphi keine Warnung aus, dass die Variable lFile möglicherweise nicht initialisiert worden ist.

Delphi-Quellcode:
var
  lFile: TNativeXML;
begin
   try
     lFile := TNativeXml.CreateName('xyz');
     [...]
   finally
      lFile.Free;
   end;
end;
So rum schon.

Der Fehler das Create in das try zu schieben wird oft und gerne gemacht. Auch ist die Frage der Anwendung des FreeAndNil() auf eine lokale Variable fraglich, aber FreeAndNil() ist besser und sicherer - steht an vielen Ecken. Damit wird es oftmals auch sehr oft eingesetzt. Im zweiten Falle kommt die Warnung von Delphi und es fällt auf, dass der Constructor Aufruf innerhalb des try/finally steht. Wenn aber nun FreeAndNil() verwendet wird, dann nicht. Hintergrund ist einfach nur, dass FreeAndNil() einen var Parameter und damit kann der Compiler dies nicht mehr erkennen, da die Funktion die Variable innerhalb ihrer belegen kann.

FYI

jfheins 14. Jul 2009 16:25

Re: try .. except .. finally
 
Hier mal meine Meinung:

Delphi-Quellcode:
begin
   ppFile := TNativeXml.CreateName('xyz');
   try
      try
         [...]
      except
        on e: EMySQLException do
         AddLogAlert('Fehler' + ppFile.ErrorMessage);
        on e: Exception do
        begin
          AddLogAlert('Fehler' + e.ErrorMessage);
          raise;
        end;
      end;
   finally
      ppFile.Free;
   end;
end;
:arrow: In so einem Fall braucht man das finally, da man ja Exceptions re-raisen kann ("Soll sich doch wer anderes damit rumschlagen")
:arrow: finally nach except, damit man im Except noch auf das Objekt zugreifen kann (und evtl. Infos heraauszuholen

mjustin 14. Jul 2009 16:29

Re: try .. except .. finally
 
Zitat:

Zitat von Surrounder
Dass es so richtig ist weiss ich, es funktionier ja auch. Ich wollte ja wissen warum es nicht wie folgt geht:

Delphi-Quellcode:
begin
   ppFile := TNativeXml.CreateName('xyz');
   try
         [...]
   except
         AddLogAlert( 'Fehler' );
   finally
      ppFile.Free;
   end;
end;

Weil es dann fast wie Java oder C# aussehen würde? ;)

Ehrlich gesagt, fände ich es auch praktisch und lesbarer. Die Reihenfolge (erst except, dann finally) würde man nicht versehentlich verdrehen. Und wenn der Bereich Exceptionbehandlung eine Vereinfachung erhält, werden mehr Entwickler auf dieses Sprachfeature aufmerksam. Viele Entwickler nutzen Exceptions nicht und benutzen Returncodes zur Fehlerbehandlung (if MyFileSize < 0 then IrgendwasSeltsamesIstGeschehen).

Cheers,

angos 14. Jul 2009 16:37

Re: try .. except .. finally
 
Hi,


Zitat:

Zitat von Muetze1
Zitat:

Zitat von angos
So herum ist es richtig.

Wieso sollte? Wer sagt dir das? [...]


und später schreibst du:
Zitat:

Zitat von Muetze1
Der Fehler das Create in das try zu schieben wird oft und gerne gemacht.

Und exakt genau das wollte ich mit dem "So herum ist es richtig." ausdrücken. Er hat nämlich das Create in das try gesetzt und genau das habe ich an dem Source angepasst ;)

Grüße
Ansgar

Christian Seehase 14. Jul 2009 17:22

Re: try .. except .. finally
 
Moin Zusammen,

um es mal allgemein zu schreiben (wenn man denn einen try/except-Block braucht:

Delphi-Quellcode:
try
  <Resource belegen>
  try
    <Mit der Resource arbeiten>
  finally
    <Resource freigeben>
  end;
except
  <Ausnahme behandeln>
end;
Da es in dem konkreten Fall darum geht, dass eine Datei evtl. gesperrt ist, wäre es allerdings besser dies zu prüfen (z.B. durch den Versuch diese mit CreateFile exklusiv zu öffnen), und den Programmablauf an das Ergebnis der Prüfung anzupassen.
Mit try/except sollte man nur dann arbeiten, wenn es wirklich nicht anders geht.

Muetze1 14. Jul 2009 17:40

Re: try .. except .. finally
 
@angos: Sorry, dann hatte ich das falsch verstanden, ich hatte das "richtig herum" auf die Verschachtelung except/finally bezogen.

Zitat:

Zitat von Christian Seehase
Mit try/except sollte man nur dann arbeiten, wenn es wirklich nicht anders geht.

Warum? Ich hätte hier auch gerne eine Begründung zu dieser Aussage.

mjustin 14. Jul 2009 18:07

Re: try .. except .. finally
 
Zitat:

Zitat von Christian Seehase
Moin Zusammen,

um es mal allgemein zu schreiben (wenn man denn einen try/except-Block braucht:

Delphi-Quellcode:
try
  <Resource belegen>
  try
    <Mit der Resource arbeiten>
  finally
    <Resource freigeben>
  end;
except
  <Ausnahme behandeln>
end;

Das finally würde ich ans Ende setzen. Kleines Praxisbeispiel, Preisfrage: wird der Fehlerdialog angezeigt?

Delphi-Quellcode:
var
  SL: TStrings;
  S: string;
begin

try
  // Resource belegen
  SL := TStringlist.Create;
  try
    // Mit der Resource arbeiten
    S := SL[1];
  finally
    // Resource freigeben
    FreeAndNil(SL);
  end;
except
    // Ausnahme behandeln
    on E:Exception do
    begin
      ShowMessage(E.Message + Format(' - S hat %d Elemente', [SL.Count]));
    end;
end;

end;

Muetze1 14. Jul 2009 18:13

Re: try .. except .. finally
 
Das Problem was hier vorliegt: Du unterscheidest nicht, welche Exception aufgetreten ist. Du gehst in deinem Except Block fest davon aus, dass es ein Bereichsfehler/Indexfehler ist. Was aber wenn der Speichermanager das Create gar nicht durchführen konnte? Dann ist deine SL Variable so oder so im Eimer, egal wie rum except und finally stehen.

Grundlegend: Ich würde niemals mit Objekten in einem Exception Abschnitt arbeiten aus dem geschützten/umfassten Codebereich. Wenn gibt es Exceptions welche zusätzliche Informationen tragen bzw. tragen können. Aber ein Zugriff auf die Objekte aus dem geschützten Bereich im Exception - Behandlungsbereich ist nicht sicherer als innerhalb des Blockes.

Eine Exception ist eine definitive Ausnahmesituation. Wenn bei dir die Küche brennt willst du dir bestimmt auch nicht vorher nochmal in Ruhe die Hände waschen bevor du dein Telefon anfässt um die Feuerwehr zu rufen - nur weil du es sonst auch immer machst (um dein Handy sauber zu halten). Wenn eine Ausnahmesituation auftritt, dann benutze verlässliche Quellen und das ist in diesem Falle die Exception selbst.

Zitat:

Zitat von mjustin
Preisfrage: wird der Fehlerdialog angezeigt?

Antwort D der 3 möglichen: Der Code geht so nicht durch das QM und wird dir um die Ohren gehauen.

mjustin 14. Jul 2009 18:52

Re: try .. except .. finally
 
Zitat:

Zitat von Muetze1
Wenn bei dir die Küche brennt willst du dir bestimmt auch nicht vorher nochmal in Ruhe die Hände waschen bevor du dein Telefon anfässt um die Feuerwehr zu rufen - nur weil du es sonst auch immer machst (um dein Handy sauber zu halten). Wenn eine Ausnahmesituation auftritt, dann benutze verlässliche Quellen und das ist in diesem Falle die Exception selbst.

Genau das wollte ich zeigen: die finally-Behandlung (das 'Händewaschen', um im Beispiel zu bleiben) hat den Effekt, dass wichtige Kontextinformationen verloren gehen. Genau wie Du es schreibst, soll daher die Exceptionbehandlung zuerst erfolgen. Wie soll man sonst in den Fällen wo es möglich ist, die Exception sauber zu behandeln, den aktuellen Zustand der Anwendung nutzen, wenn man sie per finally zuerst wieder initialisiert, und wie soll man sinnvolle Kontextinformationen wie z.B. Kundennummer auch protokollieren, wenn man im finally schon das Kundenobjekt entsorgt hat? Und so quasi das Handy aus dem Fenster wirft, um es vor den Flammen zu retten ;)

Ob die Reihenfolge try ... finally ... except ... end oder try ... except ... finally ... end verwendet wird, macht daher schon einen Unterschied. C# und Java zum Beispel kennen nur try catch finally. Also erst "die Feuerwehr rufen", nicht als letztes.

Christian Seehase 14. Jul 2009 18:55

Re: try .. except .. finally
 
Moin Muetze,

Zitat:

Zitat von Muetze1
Zitat:

Zitat von Christian Seehase
Mit try/except sollte man nur dann arbeiten, wenn es wirklich nicht anders geht.

Warum? Ich hätte hier auch gerne eine Begründung zu dieser Aussage.

Wie der Name schon sagt, handelt es sich hier um eine Ausnahme, demzufolge finde ich es einfach sauberer mögliche Fehlerbedingungen selber zu prüfen, als es "drauf ankommen zu lassen", und die Programmsteuerung durch Exceptions zu regeln.
Zudem dauert die Verarbeitung einer Exception IMHO relativ lange, und wenn man sich erst einmal daran gewöhnt hat alle möglichen Fehlerbedingungen nicht selber zu prüfen, könnte es sich auch negativ auf das Laufzeitverhalten auswirken.

mjustin 14. Jul 2009 19:04

Re: try .. except .. finally
 
Zitat:

Zitat von Christian Seehase
Moin Muetze,

Zitat:

Zitat von Muetze1
Zitat:

Zitat von Christian Seehase
Mit try/except sollte man nur dann arbeiten, wenn es wirklich nicht anders geht.

Warum? Ich hätte hier auch gerne eine Begründung zu dieser Aussage.

Wie der Name schon sagt, handelt es sich hier um eine Ausnahme, demzufolge finde ich es einfach sauberer mögliche Fehlerbedingungen selber zu prüfen, als es "drauf ankommen zu lassen", und die Programmsteuerung durch Exceptions zu regeln.
Zudem dauert die Verarbeitung einer Exception IMHO relativ lange, und wenn man sich erst einmal daran gewöhnt hat alle möglichen Fehlerbedingungen nicht selber zu prüfen, könnte es sich auch negativ auf das Laufzeitverhalten auswirken.

Exceptions verlangsamen ein Programm nicht, solange sie nicht ausgelöst werden. Und sie haben gegenüber klassischem Returncode-basierten Fehlerstatus-Behandlungen Vorteile. Man muss keine speziellen Returnwerte für Fehlerstati reservieren, und sie können mehr Informationen zum Fehlerkontext transportieren.

Manchmal ist eine Behandlung eines Fehlers auch nicht allgemeingültig möglich, z.B. wenn die gleiche Funktion mal in einer GUI, in einem Batchjob oder einem Webservice verwendet wird. Statt
Delphi-Quellcode:
if GUIVorhanden then Benutzerfragen ... else
kann man dann einfach die Exception werfen und die konkrete Anwendung der Funktion entscheidet, wie sie mit der Fehlersituation umgehen möchte.

Satty67 14. Jul 2009 19:08

Re: try .. except .. finally
 
Zitat:

Zitat von Surrounder
Delphi-Quellcode:
begin
   try
     [...]
   except
     AddLogAlert( 'Fehler' );
   finally
     ppFile.Free;
   end;
end;

Wie schon bemerkt wurde, ist das falsch, fände es aber eigentlich ganz praktisch... So in der Art wie If else If Blöcke.

Mal als Erweiterungsvorschlag einreichen... 8)

mjustin 14. Jul 2009 19:15

Re: try .. except .. finally
 
Zitat:

Zitat von Muetze1
Was aber wenn der Speichermanager das Create gar nicht durchführen konnte? Dann ist deine SL Variable so oder so im Eimer, egal wie rum except und finally stehen.

Und umgekehrt: wenn es schon Probleme mit dem Speichermanager gibt, dann spielt der restliche Code auch keine grosse Rolle mehr. Oder wird, damit das QM zufrieden ist, dann ein automatisches Einstecken von mehr RAM Bausteinen ausgelöst ? :)

SCNR

Muetze1 14. Jul 2009 19:58

Re: try .. except .. finally
 
Zitat:

Zitat von mjustin
Zitat:

Zitat von Muetze1
Was aber wenn der Speichermanager das Create gar nicht durchführen konnte? Dann ist deine SL Variable so oder so im Eimer, egal wie rum except und finally stehen.

Und umgekehrt: wenn es schon Probleme mit dem Speichermanager gibt, dann spielt der restliche Code auch keine grosse Rolle mehr. Oder wird, damit das QM zufrieden ist, dann ein automatisches Einstecken von mehr RAM Bausteinen ausgelöst ? :)

Wer nun nicht an Beispielen erkennt das die aufgezeigten Probleme auch nur beispielhaft sind, der hat nicht das Prinzip nicht verstanden.

TStringList hat nun nicht soviele mögliche Exceptions und eine Exception im Konstruktor wird von ihr soweit auch nicht verwendet, von daher ist es ein Beispiel gewesen. Es gibt genug Objekte in der freien Wildbahn welche weit andere Exceptions werfen. Und es nochmals daran erinnert, dass die einzige Möglichkeit einen Konstruktor abzubrechen das werfen einer Exception ist und somit hier nicht als Ding der Unmöglichkeit von der Hand zu weisen ist.

Und wenn du QM so witzig findest, scheint dies bei dir/euch wohl auch genauso gehandhabt zu werden und somit ist die Frage was nach deren Prüfung am Ende heraus gegeben wird.

Zitat:

Zitat von Satty67
Mal als Erweiterungsvorschlag einreichen... 8)

Wurde CodeGear/Embarcardero schon vorgeschlagen und es wird für das nächste Release überlegt, da sie die Sprache samt Compiler eh nochmals umkrempeln.

Christian Seehase
Wie der Name schon sagt, handelt es sich hier um eine Ausnahme, demzufolge finde ich es einfach sauberer mögliche Fehlerbedingungen selber zu prüfen, als es "drauf ankommen zu lassen", und die Programmsteuerung durch Exceptions zu regeln.


Und da liegt der Hund begraben: persönliche Ansichten.

Aber grundlegend hast du vollkommen Recht und ich stimme dir auch voll zu. Die Fehlerbehandlung darf durch die Nutzung der Exceptions nicht gänzlich entfallen, das ist der falsche Weg. Das habe ich so auch nie propagandiert. Eine Exception ist immer eine Ausnahmesituation, aber eine fehlgeschlagene Funktion ist dies noch lange nicht. Von daher ist die normale Fehlerbehandlung weiterhin wichtig und gefordert. Da sind wir uns auch komplett einig, von daher hast du mich vllt. falsch verstanden.

Exceptions sind dazu gedacht auf Situationen hinzuweisen welche so nicht gedacht und/oder geplant waren. Wenn geplant war, dass eine Funktion fehlschlagen kann, dann kann sie ein entsprechenden negativen Rückgabewert o.ä. geben. Eine Exception hingegen weist auf eine ganz andere Situation neben den geplanten Abläufen hin.

Wenn ich eine vom Benutzer ausgewählte Datei öffnen will, dann kann ich mit FileExists() prüfen ob diese existiert. Dann öffne ich sie und gehe auch davon aus diese benutzen zu können. Wenn diese aber durch einen anderen Prozess exklusiv geöffnet ist oder der Nutzer entgegen besseren Wissens uns eine schreibgeschützte Datei zum Speichern ausgewählt hat, so ist dies eine Situation die neben dem geplanten Ablaufstrang liegt. Diese Situation ist eine Exception wert und hier auch sinnvoll. Gerade dies Beispiel zeigt auf, dass man einfach nicht alles durch vorherige Abfragen abprüfen kann. Ich könnte neben FileExists natürlich noch die Attribute prüfen, aber nützt nichts, wenn ich die Datei aufgrund von fehlenden Rechten nicht öffnen kann. Nun gut, wenn ich Zeit habe erkenne ich noch das Dateisystem und checke dann die Rechte der Datei + Rechtekontext in dem die App läuft und dann ob ich damit die Datei öffnen kann. Bringt mir auch noch nichts, wenn ein anderer Prozess diese Datei hat. Ok, also das auch noch abprüfen und dann habe ich ein Problem, wenn der Nutzer auf eine Netzwerkfreigabe gegangen ist, etc, etc, etc.

Grüsse,
Muetze1

mjustin 14. Jul 2009 20:13

Re: try .. except .. finally
 
Zitat:

Zitat von Muetze1
Und es nochmals daran erinnert, dass die einzige Möglichkeit einen Konstruktor abzubrechen das werfen einer Exception ist und somit hier nicht als Ding der Unmöglichkeit von der Hand zu weisen ist.

Das hat ja auch niemand behauptet, mein Beispiel war eventuell nicht minimal genug. Ich wollte damit vor allem nur darstellen, dass die Reihenfolge finally ... except eher ungünstig ist. Dass in meinem Beispiel auch noch andere Dinge enthalten waren, über die sich trefflich streiten lässt, hat den Blick auf die Kernfrage (zuerst das finally, oder erst das except?) etwas verstellt.

Cheers,

Muetze1 14. Jul 2009 20:19

Re: try .. except .. finally
 
Zitat:

Zitat von mjustin
Zitat:

Zitat von Muetze1
Und es nochmals daran erinnert, dass die einzige Möglichkeit einen Konstruktor abzubrechen das werfen einer Exception ist und somit hier nicht als Ding der Unmöglichkeit von der Hand zu weisen ist.

Das hat ja auch niemand behauptet, mein Beispiel war eventuell nicht minimal genug. Ich wollte damit vor allem nur darstellen, dass die Reihenfolge finally ... except eher ungünstig ist. Dass in meinem Beispiel auch noch andere Dinge enthalten waren, über die sich trefflich streiten lässt, hat den Blick auf die Kernfrage (zuerst das finally, oder erst das except?) etwas verstellt.

Ich verstehe dich dann nicht. Gerade dein Beispiel mit dem äusseren except Block und der Nutzung der Variablen im Exception Handler stellt doch das Problem dar: du benutzt eine Variable die nicht sicher ist, da die Exception eine Initialisierung der selbigen verhindert hat.

Und gerade dadurch wird die Kernfrage doch schon geklärt: Wenn du Dinge aus dem inneren Block nutzen willst, dann muss der Except Block innerhalb von finally stehen. Wenn aber nicht, dann lieber ausserhalb, weil sonst die Gültigkeit der lokalen Daten welche mit finally definitiv freigegeben werden sollen, unnötig verlängert wird.

Christian Seehase 14. Jul 2009 22:20

Re: try .. except .. finally
 
Moin Muetze,

Zitat:

Zitat von Muetze1
Da sind wir uns auch komplett einig, von daher hast du mich vllt. falsch verstanden.

Ich denke nicht, dass ich Dich falsch verstanden habe.
Du wolltest ja nur eine Begründung habe, warum ich der Ansicht bin, dass man Exceptions nur Ausnahmsweise verwenden sollte ;-)

@Michael:
Schon klar, dass eine nicht ausgelöste Exception das Programm nicht verlangsamt.
Ich habe nur schon gesehen, dass diese intensiv benutzt werden um, oft simple, Prüfungen zu ersetzen, so dass die Exceptions recht häufig geworfen werden, und dann kann es sich durchaus als Bremse erweisen.

Surrounder 14. Jul 2009 22:22

Re: try .. except .. finally
 
Dass ich jetzt so eine Diskussion vom Zaun breche wollte ich nicht, also vertragt Euch wieder :kiss:

Zitat:

Zitat von Muetze1
Wenn ich eine vom Benutzer ausgewählte Datei öffnen will, dann kann ich mit FileExists() prüfen ob diese existiert. Dann öffne ich sie und gehe auch davon aus diese benutzen zu können. Wenn diese aber durch einen anderen Prozess exklusiv geöffnet ist oder der Nutzer entgegen besseren Wissens uns eine schreibgeschützte Datei zum Speichern ausgewählt hat....


Das was Muetze1 beschrieben hat trifft bei mir exakt zu, ich prüfe natürlich mit FileExists ob die Datei auch wirklich da ist, öffne Sie dann und versuche dann meine Daten zu schreiben. Die Datei gibt es auch, aber der User hat keine Rechte auf dem Pfad und ich kann die Datei zwar öffnen, aber eben nicht den Inhalt schreiben.
Mir war es nun genau zu viel Aufwand hier sämtliche Dinge zu prüfen, da es sich sowieso um eine Ausnahmesituation handelt wollte ich das als Excpetion abfangen. Ich komme ansonsten halt vom 100ten ins 1000ste und bin nur noch am prüfen und machen bevor ich zum eigentlichen Sinn meiner Software komme.

Meine Frage war ja auch nur warum ich keinen try .. except .. finally Block machen kann, weil mir das in diesem Moment einfach logisch erschien. Ich habe aber nun verstanden dass die Syntax das eben nicht vorsieht :cheer:

alzaimar 15. Jul 2009 06:46

Re: try .. except .. finally
 
Wir hatten schon diverse Diskussionen zum Thema 'Exceptions: Geißel oder Segen?'. Oder auch: 'Oute ich mich als Versager, wenn ich mit Try..Except arbeite'.

Ich werde mal wieder meine Meinung zum Besten geben:
Ein Grundsatz robuster Softwareentwicklung ist, das innere Exceptions nicht nach außen dringen sollen. Ich muss also *alle* Exceptions abfangen, behandeln und ggf. in andere Exceptions übersetzen. Jede öffentliche Klasse sollte auch einen Satz von eigenen Exceptions mitbringen, in die die inneren Exceptions ggf. übersetzt werden.

Was bringt dem Anwender eine Exception der TCP-Klasse? Er versteht sie nicht, er wollte mit TCP nix am Hut haben, also: Gar nichts. Ihm ist es auch egal, das der Programmierer einen SQL-Befehl falsch geschrieben hat. Er will klare und verständliche Fehlermeldungen. in der Logdatei kann der Fehler ja stehen, aber nicht auf dem Bildschirm.

Für mich (und u.A. auch die Erfinder moderner Programmiersprachen) sind Try-Except Blöcke ein Segen, denn sie erlauben mir, einen klaren Programmfluss, der eben nicht durch ständige Abfragen von Präkonditionen unleserlich gemacht wird. Denn Eine Exception ist die Ausnahme, der Code wird also i.d.R. so abgearbeitet, wie ich es wollte, nur eben in Ausnahmen nicht. Die sind i.d.R. gravierend und führen dann zum Abbruch der Aktion.
D.h. natürlich nicht, das ich auf sämtliche Präkonditionen verzichte, aber da ich sowieso nicht alle Fehler von vorne herein abfangen kann, beschränke ich mich auf die, die den Code leserlicher machen.

Beispiel: Ich kann schauen, ob eine Datei, aus der ich lesen will, existiert. Aber wozu soll ich vorher prüfen, ob die Datei korrupt ist? Da lass ich den Karren doch lieber an die Wand fahren und kratze die überbleibsel ab und analysiere sie.

Gut, Try-Except macht also Sinn. Alle sichtbaren Methoden sind mit einem Try-Except-Block gekapselt, und sei es, um die Logdatei zuzumüllen.

Das ich zudem in den meisten Methoden irgendwelche Klassen instantiiere, die ich im Finally-Block wieder freigebe, folgt daraus, das alle Methoden nach dem Motto: Reservieren-Ausführen-Fehler behandeln-Freigeben implementiert werden.
Delphi-Quellcode:
Try
 ...
Except
  LogDenFehler;
Finally // << --- unnötig
  WaschDieHände;
End;
Ist hübsch aber überflüssig, denn der Fehler wird nicht weitergereicht, also braucht man auch den Finally-Block nicht.

Ich konvertiere Fehler und leite sie weiter, denn Fehler sind schwerwiegend und keine Bagatelldelikte. Also wäre mir ein kompakter Try-Except-Finally-Block angenehm.
Delphi-Quellcode:
Try
 ...
Except
  LogDenFehler;
  LeiteIhnWeiter; // <<---
Finally
  WaschDieHände;
End;
Ich nehme mal an, die Java- und C#-Erfinder haben sich so etwas ähnliches dabei gedacht, also sie die kombinierten Try-Catch-Finally-Blocke ins Sprachkonzept aufgenommen haben. Das sie bei Delphi fehlen, ist schade, aber es gibt Schlimmeres.

GreenHorn3600 15. Jul 2009 23:06

Re: try .. except .. finally
 
Zitat:

Zitat von angos
Delphi-Quellcode:
[...]
begin
   ppFile := TNativeXml.CreateName('xyz');
   try
      try
         [...]
      except
         AddLogAlert( 'Fehler' ); //<< Was passiert, wenn hier ein Fehler auftaucht?
      end;
   finally
      ppFile.Free;
   end;
end;

Was mich Interessieren würde ist, was passiert, wenn im AlertLog ein Fehler auftritt, z.B. weil der Arbeitsspeicher aus ist oder die Platte korrupt und das Finally weggelassen wurde. Werden dann dennoch die Ressourcen freigegeben oder verbleiben die im Speicher?

Nachdenkliche Güße
GreenHorn

himitsu 16. Jul 2009 06:12

Re: try .. except .. finally
 
wenn in AddLogAlertein Fehler auftritt, dann wird ppFile immernoch freigegeben
und danach die Exception von AddLogAlert nach außen weitergereicht.

alzaimar 16. Jul 2009 07:02

Re: try .. except .. finally
 
Die Methode AddLogAlert hat natürlich einen eigenen Exception-Handler, der etwaige Probleme abfängt. Was interessiert den Programmierer, ob die Platte korrupt ist? Das muss die IO-Schicht abfangen und ggf. eine fatale Exception werfen, oder im Hintergrund eine neue Festplatte downloaden und sofort installieren. :stupid:

Hier ist uns Java überlegen, wo man in der Methodendeklaration gleich noch angibt, welche Exceptions auftreten können.

Khabarakh 16. Jul 2009 08:24

Re: try .. except .. finally
 
Zitat:

Zitat von alzaimar
Hier ist uns Java überlegen, wo man in der Methodendeklaration gleich noch angibt, welche Exceptions auftreten können.

Segen... oder Fluch ;) ?

The Trouble with Checked Exceptions. A Conversation with Anders Hejlsberg

Dort wird auch genannt, warum ich keine große Notwendigkeit für try-except-finally sehe:
Zitat:

It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch.
Gut, C# besitzt sowas :stupid: , aber dort habe ich sowieso noch nie ein finally benötigt :stupid:² .


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