![]() |
ersetzt try..except begin..end?
Moin,
eine Frage zur Hierarchie bei der Codeabarbeitung: entspricht
Delphi-Quellcode:
?
if Moin then
try //.. except end; if Moin then begin //... end; Grüße, Messie |
Re: ersetzt try..except begin..end?
nein aber:
Delphi-Quellcode:
if Moin then
try //.. except end; if Moin then try begin end; except begin end; end; |
Re: ersetzt try..except begin..end?
wäre nie auf die idee gekommen, aber bei mir tuts das sehr wohl.
|
Re: ersetzt try..except begin..end?
Habe es mal getestet,
Delphi-Quellcode:
Es wird keine der Messages angezeigt.i := 0; If i = 1 Then Try ShowMessage('1'); ShowMessage('2'); Except End;
Delphi-Quellcode:
Es wird ebenfalls keine der Messages angezeigt.
i := 0;
If i = 1 Then Begin ShowMessage('1'); ShowMessage('2'); End;
Delphi-Quellcode:
Es wird Message 2 angezeigt.
i := 0;
If i = 1 Then ShowMessage('1'); ShowMessage('2'); Somit ist klar, dass try..except sich diesbezüglich wie begin..end verhält |
Re: ersetzt try..except begin..end?
doch. eigentlich lässt sich die frage mit "ja" beantworten. der try..except-block würde nur bei moin=true ausgeführt - genau wie der begin..end-block.
|
Re: ersetzt try..except begin..end?
Dafür gibt es zwei Referenzen:
a) die Delphi-Hilfe b) der Borland Style-Guide Zwischen try und except gehört kein begin / end. Genauso wenig wie zwischen except und dem dazugehörenden end. also soll es so aussehen:
Delphi-Quellcode:
try
Anweisung1; Anweisung2; Anweisung3; except Anweisung4; Anweisung5; end; |
Re: ersetzt try..except begin..end?
Das ist doch im Prinzip das Gleiche wie bei repeat until, da wird alles was da zwischen ist eingeschlossen un smoit kein begin end benötigt...
|
Re: ersetzt try..except begin..end?
Wenn ich nach except auf die Exception-Klasse Zugriff haben will, bekomme ich den nur mit
Delphi-Quellcode:
Also nicht ganz eindeutig. Zumal in dem Beispiel nur hierarchisch gleiche Anweisungen vorkommen. Ich hab' öfter mal verschachtelte try..except und try..finally-Blöcke.
try
//.. except on e:meineException do begin //.. end; end; Wo finde ich denn den Style Guide? Grüße, Messie |
Re: ersetzt try..except begin..end?
Den Style-Guide (oder zumindest Hinweise darauf) sollte mit der Suche hier im Forum zu finden sein.
Ansonsten google mit entsprechenden Begriffen füttern. Verschachtelte try..except funktionieren auch ohne begin/end. |
Re: ersetzt try..except begin..end?
try..except..end ist genau wie begin..end, repeat..until, while..end, case..end eine Anweisung (mit der Besonderheit, dass innderhalb dieser Anweisung weitere Anweisungen stehen können). Eine solche Anweisung kann überall stehen, wo auch eine 'normale' Anweisung stehen kann und wird als ganzes abgearbeitet.
Insofern lautet die Antwort: Nein. Begin..end wird nicht 'ersetzt' es ist eine gleichwertige Anweisung (oder auch Anweisungsblock, wers lieber mag). Ein try..except kann auch ein a:=7; 'ersetzen'. Ich persönlich halte es aber für sinnvoller, try..except nach einem If trotzdem in einem Begin..End zu kapseln, da sich dadurch die Lesbarkeit erhöht. |
Re: ersetzt try..except begin..end?
Zitat:
Du kannst ja auch schreiben
Delphi-Quellcode:
...
except on e:EEineException do begin TuWasMitderEinenException ... end; on e:EAndereException do begin TuWasMitderAndereException ... end; end; |
Re: ersetzt try..except begin..end?
Zitat:
Delphi-Quellcode:
while (...) begin
end; |
Re: ersetzt try..except begin..end?
Zitat:
Delphi-Quellcode:
Ich glaube ja, Sidorion meint das gleiche wie du.
while (...) do begin
end' |
Re: ersetzt try..except begin..end?
Zitat:
Laut Styleguide gehört nach einem if immer ein begin/end. Da ist es egal, ob ein try..except-Block oder ne Anweisung oder ein anderer Anweisungsblock kommt. Ich vermute mal, die meisten hier haben noch nie in einer grösseren Firma gearbeitet, wo mehrere Leute gleichzeitig am selben Projekt arbeiten. Da MUSS man nach Styleguide arbeiten, weil nicht erst jeder den Code nach seinen Belieben umformatieren kann. Wenn ich alleine in meinem Kämmerlein an einem Projekt arbeite, dann kann ich mir schon einen eigenen exotische n Stil überlegen, sodass keiner mehr mit dem Code klarkommt. |
Re: ersetzt try..except begin..end?
Da war ich wieder mal zu schnell und hab nicht genug nachgedacht :oops:
Was du geschrieben hast meinte ich... Es ging mir darum, dass bei while halt doch begin end benötigt wird. |
Re: ersetzt try..except begin..end?
Ich meinte While..do :). Allerdings fällt mir grad auf, dass while nicht in die Aufzählung von mir passt (genau wie for und if), da dieses eine Einzelanweisung ist, die lediglich die folgende mehrfach wiederholt.
p.s.: Sorry ich wollte keinen Kleinkrieg über Styles lostreten. Asche auf mein Haupt. |
Re: ersetzt try..except begin..end?
Zitat:
Edit: Buchstabendreher |
Re: ersetzt try..except begin..end?
Zitat:
Delphi-Quellcode:
try
// ... except if ExceptObject is meinException then ShowMessage(meinException(ExceptObject).DeineMessage) else if ExceptObject is andereException then ShowMessage(andereException(ExceptObject).AndereMessage) else ShowMessage(Exception(ExceptObject).ClassName + ' ' + Exception(ExceptObject).Message); end; |
Re: ersetzt try..except begin..end?
Delphi-Quellcode:
Kannst du das äußere begin end gleich nach der IF Abfrage weg lassen ohne das sich was an der Funktionalität verändert ?
if x then
begin try except end; end; Ja, also ist es sinnvoll es auch wegzulassen da es ein redundanter Source ist. Jeden überflüssige Zeile im Source sollte nach Möglichkeit auch eliminiert werden da sich so zwangsläufig die Lesbarkeit und damit Verständlichkeit des Sources erhöht.
Delphi-Quellcode:
Bei
if x then
begin try except end; end else begin try except end; end; // würde so aussehen if x then try except end else try except end;
Delphi-Quellcode:
ist es schon wieder eine andere Pronlematik. zb. wenn
if x then
begin try finally end; end;
Delphi-Quellcode:
Der letzere Falle ist deshalb eine Krücke da wir ja auch verschachtelte IF Abfragen haben könnten. Es verführt dann dazu gleich am Begin einer Funktion alle diese Objecte erstmal auf nil zu setzen. Je nach Path werden aber bestimmte Variablen dann garnicht benötigt und das fürht dazu das der Compiler schlechter den besten Code erzeugen kann, eben weil wir die Variablen schon in Advance benutzt haben.
if x then
begin Object := TObject.Create; try finally Object.Free; end; end; // falsch wäre hier if x then try Object := TObject.Create; finally Object.Free; end; // oder unellegant wäre Object := nil; if X then try Object := TObject.Create; finally Object.Free; end; In diesem Falle wäre also ein begin end mit enthaltenem try finally Block sauberer. Gruß Hagen |
Re: ersetzt try..except begin..end?
Zitat:
Grüße, Messie |
Re: ersetzt try..except begin..end?
Zitat:
Wir wissen: ExceptObject ist eine globale Variable. Ist sie auch eine Threadeigene globale Variable -> threadvar ? Wenn nicht kann innerhalb deiner verschachtelten IF Abfragen das ExceptObject als globale Variable durch eine Exception innerhalb eines parallelen Threads verändert werden. Man sollte also wirklich
Delphi-Quellcode:
benutzen. In diesem Moment verhält sich das on E: Exception do wie ein with Variable do Anweisung. Der Compiler wird dann in der lokalen Variable E das aktuelle Exception Object zur Verfügung halten, statt bei jeder IF Abfrage auf ein globales Object zuzugreifen. Davon abgesehen ist das SEH unter Windows Stackbasiert und mit der Abfrage on E: Exception do greifen wir nur auf diesen Stack und damit Threadbezogen auf das einzigste gültige Exception Object zu. Die globale Variable ExceptObject ist also eher eine Krücke damit bestimmte Objekte wie TApplication ein eigene Handling von Exception machen können.
try
except on E: Exception do if E is EAbort then ... else if E is EInOutError then ... else reraise; end; Gruß Hagen |
Re: ersetzt try..except begin..end?
@messie: Weil der Konstruktor fehlschlagen kann, und dann wäre da nichts zum freigeben. Weiterhin stimmt der Kontext nicht: Der Try..Finally-Block soll ja gerade die Verwendung des OPbjektes schützen und nicht die Instantiierung selbst.
Richtig wäre es so:
Delphi-Quellcode:
@NegaH: Ich mag es aber in grün lieber:
Try
Obj := TMyObect.Create; Try Obj.Foobar Finally Obj.Free Finally Showmessage('Ach Du scheisse, noch nich mal Create funzt.') End;
Delphi-Quellcode:
Try
... Except On E:EThisException Do Begin HandleThisException(E); End; On E:EThatException Do Begin HandleThatException (E); End; On E:Exception Do Begin HandleAnyOtherException (E); End; End; |
Re: ersetzt try..except begin..end?
@Messie:
Zitat:
Erst nachdem der Konstruktor erfolgreich zurückkehrt. Und was würde passieren wenn der Konstruktor eine Exception auslösst ? Zb. wegen's Speichermangel oä. ? Dann würden wir sofort im finally end; Block landen. Ist dann die Variable Object wirklich initialisert wurden ? Nein, in Object würde irgendwas stehen, also vorherige Daten aus dem Stack oder einem CPU Register. Wozu führt dies ? Das bei Object.Free; wir ein Object freigeben würden das garnicht also solches existent ist. Nur wenn Object durch dummen Zufall nil =$00000000 wäre würde es keine Zugriffsveretzung geben. Dieser Fall tritt mit exakt 1/2^32 Wahrscheinlichkeit ein, also sehr unwahrscheinlich. Gruß Hagen |
Re: ersetzt try..except begin..end?
@Alzaimar:
Zitat:
Delphi-Quellcode:
1.) Lesbarkeit, bzw. Explizität dessen was man schreibt, nichts ist zuviel oder zu wenig umschrieben.
try
except on E: Exception do if E is EThisException then HandleThisException(E) else if E is EThatException then HandleThatException(E) else HandleAnyException(E); end; 2.) ob man on E: XYZ do abfragt oder E is XYZ ist egal, dahinter wird der Compiler den gleichen Code erzeugen, für die Klassentyp Abfrage. 3.) Programablaufpfad, bei deiner Lösung fragst du unnötigerweise mit wesentlich höherer Wahrscheinlichkeit die Exception Klasse ab. Bei meinem wird auf grund der kaskadierten IF Abfrage die Wahrscheinlichkeit das zb. HandleAnyException() aufgerufen wird drastisch reduziert das die Wahscheinlichkeiten für EThisException und ETahtException davon abzuziehen sind. Mein Vorschlag ist also effizenzter. Gruß Hagen |
Re: ersetzt try..except begin..end?
Es ginge glaub ich aus so
Delphi-Quellcode:
Das hat dann aber eine Klassenabfrage in der letzten Zeile mehr als die IF Abfrage.
try
except on E: EThisException do HandleThisException(E) else on E: EThatException do HandleThatException(E) else on E: Exception do HandleAnyException(E); end; Zudem wird bei jedem on E: XYZ do erneut aus dem SEH Frame das Exception Object geladen werden müssen. Das bedeutet 2 indirekte Specherzugriffe mehr pro dieser Abfrage. Die IF Abfrage Methode holt also nur einmalig E aus dem SEH Frame im Stack. Danach verhalten sich die IF Abfragen wie in einem with E do Block. Aus meiner Sicht also effizienter und auch leichter lesbar. Die Lesbarkeit liegt aber oft im Auge des Betrachters, die entstehdne Funktionalität aber nicht. Und exakt in diesem Punkt unterscheiden sich unsere Lösungen beträchtlich. Gruß Hagen |
Re: ersetzt try..except begin..end?
Wir können das mal herleiten.
Wir wissen das wir uns in einem absolut logischen und abgeschlossenen System bewegen, auf einem Computer und in der Syntax der Sprache Delphi.
Delphi-Quellcode:
was macht dieses,
try
except on E: Exeption do end; on E: Exception do mal ausgedrückt in Delphi, denn eigentlich ?
Delphi-Quellcode:
Nun schreiben wir die Abfrage wie sie Alzaimar benutzt um
try
except with Hole_Exception_Object_Aus_SEH in variable E do if E is Klassentyp then end;
Delphi-Quellcode:
Was wissen wir am Punkt 1.) ?
try
except with Hole_Exception_Object_Aus_SEH in variable E do if E is EThisException then begin HandleThisException(E); end; // 1.) with Hole_Exception_Object_Aus_SEH in variable E do if E is EThatException then begin HandleThatException(E); end; // 2.) with Hole_Exception_Object_Aus_SEH in variable E do if E is Exception then begin HandleAnyException(E); end; end; Wir wissen das falls die vorherige Abfrage zutreffen würde wir die Abfrage in 1.) einsparen könnten. Denn wenn E vom Typ EThisException ist dann kann sie nicht vom Typ EThatException mehr sein. Aber stellen wir uns mal vor EThisException wäre von EThatException abgeleitet ? Dann würde die erste Abfrage zutreffen und die bei 1.) und 2.) aber auch ? Macht es Sinn, bzw. ist es sogar beabsichtigt das man dann zwei bzw. sogar drei Behandlungsroutinen für eine Exception ausführt ? Meistens, ja fast immer, macht sowas keinen Sinn. Wir können also vereinfachen und sogar eventuelle logische Fehler beseitigen.
Delphi-Quellcode:
Wir kaskadieren die IF Anfragen und verkürzen so den Programablaufpfad. Der Code wird dadurch sogar noch schneller ausgeführt.
try
except with Hole_Exception_Object_Aus_SEH in variable E do if E is EThisException then begin HandleThisException(E); end else with Hole_Exception_Object_Aus_SEH in variable E do if E is EThatException then begin HandleThatException(E); end else with Hole_Exception_Object_Aus_SEH in variable E do if E is Exception then begin HandleAnyException(E); end; end; Nun stellen wir fest das die "Funktion" Hole_Exception_Object_Aus_SEH dreimalig aufrufen. Hinter jedem dieser Aufrufe versteckt sich produzierter Code, davon abgesehen ist es auch redundant. Wir vereinfachen
Delphi-Quellcode:
Wir stellen fest das die vielen begin end Blöcke überflüssige Redundanz darstellen. Das alles müssen wir beim Lesen mit den Augen erfassen, im Hirn übersetzen, und das für Nichts. Es ist demzufolge nicht explizit.
try
except with Hole_Exception_Object_Aus_SEH in variable E do if E is EThisException then begin HandleThisException(E); end else if E is EThatException then begin HandleThatException(E); end else if E is Exception then begin HandleAnyException(E); end; end; wir vereinfachen
Delphi-Quellcode:
Wir wissen das alle Exception Klassen von der Basisklasse Exception abgeleitet werden. Also ist die letzte IF Abfrage überflüssig, sie ist immer WAHR.
try
except with Hole_Exception_Object_Aus_SEH in variable E do if E is EThisException then HandleThisException(E) else if E is EThatException then HandleThatException(E) else if E is Exception then HandleAnyException(E); end; wir vereinfachen
Delphi-Quellcode:
Wir haben vorher die on E: Exception do Syntax in eine logische Form gebracht die uns besser erklärt was da vor sich geht. Diesen Abstraktionsschritt machen wir rückgängig.
try
except with Hole_Exception_Object_Aus_SEH in variable E do if E is EThisException then HandleThisException(E) else if E is EThatException then HandleThatException(E) else HandleAnyException(E); end;
Delphi-Quellcode:
Wir resümieren: Das zu lösende Problem wurde in der Delphi Syntax auf ein nicht mehr reduzierbares Maß verkürzt. Jede weitere Reduktion würde die angestebte und sinnvolle Funktionalität verändern.
try
except on E: Exception do if E is EThisException then HandleThisException(E) else if E is EThatException then HandleThatException(E) else HandleAnyException(E); end; Anders ausgedrückt: es ist eben keine Stilfrage wie man was schreibt sondern eine logisch herleitbare und sinnvoll auf ein notweniges Maß reduzierbare Aufgabe des Programmierers. Die Explizität in unseren Sourcezeilen ist also eine logische Notwendigkeit damit wir nur das exakt umschreiben was auch minimal notwendig ist um ein Problem zu lösen. Wer als Programmierer meint er müsste aus modischen Gründen es nicht so handhaben der kann defakto eben nicht programmieren. Gut das sind harte Worte, unfair vielleicht, aber im Grunde absolut richtig. Ein guter Stil zeichnet sich also dadurch aus das er explizit ist. Jede Weigerung es nicht so zu handhaben kann demzufolge nicht mehr auf logischen Gründen basierend untermauert werden. Es sind meistens emotionale Vorlieben, Sturheit, nicht Lernfähigkeit, aus Prinzip oder Gewohnheiten, aber garantiert nicht überlegtes Denken. Es stellt sich die Frage: Was machen den Programmierer den ganzen Tag lang ? Gruß Hagen |
Re: ersetzt try..except begin..end?
Hallo Hagen,
ich habe mir einmal die Mühe gemacht, beide Lösungen mit dem Debugger schrittweise zu durchlaufen. Bei dem von alzaimar vorgeschlagenen Code lande ich (nach dem Fehlerdialog) direkt im Rumpf der passenden on-Anweisung. Im Anschluß an die Fehlerbehandlung erfolgt ein Sprung zum Ende der try-Anweisung, wo das Exception-Objekt über DoneExcept aufgelöst wird. Bei deiner Lösung erfolgt der Sprung zur einzigen on-Anweisung, von dort aus wird über eine Folge von isClass-Aufrufen der passende Handler gesucht. Die Abläufe in Windows (Kernel32 und ntdll) sind bei beiden Lösungen identisch. Sollte deine Lösung dennoch effizienter sein? Mache ich vielleicht einen Denkfehler? Getestet habe ich übrigens mit Delphi 6 - mit und ohne Optimierung. Gruß Hawkeye |
Re: ersetzt try..except begin..end?
Gut jetzt kommt der unangenehme Part für mich.
Zitat:
Tatsächlich ist es so das Delphi im Grunde schon selbstständig alle on E: XYZ do Konstrukte syntaktisch als case of Abfrage umsetzt. Egal wie man es also schreibt es ist vergleichbar mit dem hier
Delphi-Quellcode:
dumerweise wird darauf zumindestens in der Delphi 5 Hilfe nicht explizit hingeweisen, ist aber keine Begründung dafür das ich falsch lag. Nicht destrotrotz verliert meine "Anleitung" dadurch nicht an allgemeiner Gültigkeit. In diesem speziellen Falle bin ich aber tatsächlich auf die syntaktischen Eigentümlichkeiten der Excpetionbehandlung herein gefallen. Man lernt halt doch nie aus ;)
try
except case Exception_Object_Type of EZeroDivide: JandleZeroDivide; EOverflow: HandleOverflow; EMathError: HandleMathError; end; end; Übrigens habe ich es selber auch noch mal getestet und mir den erzeugten Code angeschaut. Hawkeye's du hast also Recht. Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:57 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 by Thomas Breitkreuz