|
Tutorial geschlossen
|
|
Registriert seit: 10. Jun 2002 Ort: Unterhaching 11.413 Beiträge Delphi 12 Athens |
#1
Hi DP-ler,
wie versprochen fangen wir mit den Exceptions an. Exceptions sind Delphis Weg, um Fehler "abzufangen" und dem Anwender einer Anwendung darzustellen. Mit Hilfe der Konstrukte try...except...end und try...finally...end kann der Programmier im Falle einer Exception (eines Fehlers) diesen abfangen bzw. notwendige "Aufräumarbeiten" werden durchgeführt, bevor der Fehler angezeigt wird. Dieser Abschnitt des Kurses bildet die Grundlage für den nächsten. Wir werden als erstes eine Komponente beginnen, welche es uns ermöglicht die Standardfehlermeldung von Delphi zu umgehen und eigene Wege zu beschreiten. try...except...end Es gibt in der Programmierung immer wieder Bereiche, in welchen man davon ausgehen muss, dass es füher oder später zu Problemen im Code kommen wird. Die wohl üblichste Fehlerquelle ist eine falsche Eingabe durch den Benutzer. Fangen wir doch mal mit einem sehr einfachen Beispiel an. Der Nutzer soll eine Zahl eingeben, welche später für Rechenoperationen genutzt wird. Wenn der Nutzer aber etwas anderes (oder nichts) eingibt, dann liegt kein gültiger Wert für die Rechenoperation vor. Um das Beispiel ein wenig zu verdeutlichen, werden wir die folgende Prozedur etwas genauer betrachten.
Code:
Zugegeben, die Funktion ist sehr einfach. Aber anhand dieser Funktion lässt sich das ganze sehr leicht darstellen. Übergeben wird der Parameter Zahl als String. Zahl wird in eine Fließkommazahl (StrToFloat) umgewandelt. Dieser Wert wird dann genutzt als Teiler für den Wert 1000 genutzt.
function DivideIt_01(Zahl: String): String;
begin Result := FloatToStr(1000 / StrToFloat(Zahl)); end; Es gibt jetzt zwei typische, potentielle Fehlerquellen.
Code:
Das Programm versucht die Anweisung Result := FloatToStr(1000 / StrToFloat(Zahl)); auszuführen. Sollte dabei ein Problem auftreten, wird der Code innerhalb des except Blockes ausgeführt. In diesem Fall geben wir einen "freundlichen" Hinweis zurück.
function DivideIt_02(Zahl: String): String;
begin try Result := FloatToStr(1000 / StrToFloat(Zahl)); except Result := 'Der übergebene Wert ist leider ungültig'; end; end; Hinweis: Der EXCEPT Block wird nur im Falle einer aufgetretenen Exception ausgeführt. try...finally...end Oft genug geschieht es in der Programmierung, dass wir einige Resourcen (Speicher) des Computers in Anspruch nehmen müssen. Anschließend sollten wir diese Resourcen stets wieder freigeben. Wieder ein denkbar einfaches Beispiel
Code:
Dieses Beipsiel liefert uns die Anzahl der Zeilen in einer (Text-)Datei zurück. In diesem Beispiel nutze ich eine Stringliste. Als erstes muss diese initialisiert werden. Anschliessend kann die Datei geladen werden, um die Anzahl der Zeilen zu ermitteln. Am Ende wird die Stringliste wieder freigegeben.
function CountLines(FileName: String): Integer;
var Strings: TStringList; begin // ressourcen reservieren Strings := TStringList.Create; // datei in die string liste laden Strings.LoadFromFile(FileName); // zeilenanzahl zurückliefern Result := Strings.Count; // string liste wieder zerstören Strings.Free; end; Was passiert jetzt, wenn die Datei nicht existiert oder der Nutzer nicht das Recht hat diese zu öffnen? Es wird eine Exception (ein Fehler) in der Zeile Strings.LoadFromFile(FileName); erzeugt und die Verarbeitung abgebrochen. Die Zeile zum freigeben der Stringliste Strings.Free; wird nie ausgeführt, dass heißt, es ist ein kleines Speicherloch entstanden... Da kommt der try...finally...end Block recht gelegen. Dieser Block wird immer ausgeführt. Damit können wir als Programmierer garantieren, dass alle Ressourcen wieder freigegeben werden. In unserem Beispiel sähe das wie folgt aus.
Code:
Auch wenn ein Fehler beim Laden der Datei auftritt, ist garantiert, dass die Stringliste zerstört wird, unabhängig davon, ob alle vorhergehenden Schritte ausgeführt worden sind, oder nicht.
function CountLines(FileName: String): Integer;
var Strings: TStringList; begin // ressourcen reservieren Strings := TStringList.Create; try // datei in die string liste laden Strings.LoadFromFile(FileName); // zeilenanzahl zurückliefern Result := Strings.Count; finally // string liste wieder zerstören Strings.Free; end; end; Hinweis: Der FINALLY Block wird immer ausgeführt. Auch wenn mitten im Code Befehle zum Abbrechen der Prozedur oder einer Schleife (z.B. Exit, Break) auftauchen. Exceptions erzeugen Um das Erzeugen eigener Exceptions zu demonstrieren, kehren wir zu unserem ersten Beispiel zurück.
Code:
Das Erzeugen einer Exception ist denkbar einfach. Erstellt wird eine Exception durch die Einbindung des reservierten Wortes raise. Als Parameter wird ein Exception Object (bzw. ein davon abgeleitetes Objekt) erstellt. Im obigen Beispiel testen wir, ob ein leerer String übergeben wird; in diesem Fall erstellen eine Exception mit einer entsprechenden Fehlermeldung.
function DivideIt_03(Zahl: String): String;
begin if Zahl = '' then raise Exception.Create('Ein leerer Parameter ist unbrauchbar!'); Result := FloatToStr(1000 / StrToFloat(Zahl)); end; Eigene Exception-Typen deklarieren Um im späteren Verlauf eines Programmes aufgetretene Fehler leichter zu erkennen, gibt Delphi uns die Möglichkeit eigene Fehlerklassen zu erstellen.
Code:
In diesem Beispiel erstellen wir eine Fehlerklasse für leere (unbrauchbare) Parameter. Wenn wir diese Klasse als Fehlerklasse in unser letztes Beispiel integrieren, dann sieht die Funktion wie folgt aus.
type
EEmptyParam = class(Exception) public constructor Create; end; { EEmptyString } constructor EEmptyParam.Create; begin inherited Create('Ein leerer Parameter ist unbrauchbar!'); end;
Code:
Für den Anwender des Programmes ergeben sich daraus keine Änderungen, aber sehr wohl für den Programmierer, wie wir im folgenden Abschnitt (Excpetions erkennen) sehen werden.
function DivideIt_04(Zahl: String): String;
begin if Zahl = '' then raise EEmptyParam.Create; Result := FloatToStr(1000 / StrToFloat(Zahl)); end; Exceptions erkennen Nachdem wir die Exceptions verstanden, erstellt und abgefangen haben, müssen wir diese für korrektes und sinnvolles Handling nur noch wiedererkennen. Dazu gibt es in einem try...except...end Block die Möglichkeit eine Exception-Typ-Überprüfung vorzunehmen.
Code:
Durch die Überprüfung on E: Exceptiontyp können wir den Typ eines Fehlers ermitteln und entsprechend reagieren. Die folgende Liste nennt die häufigsten Fehlertypen
function DivideIt_05(Zahl: String): String;
begin try if Zahl = '' then raise EEmptyParam.Create; Result := FloatToStr(1000 / StrToFloat(Zahl)); except // leere parameter erkennung on E: EEmptyParam do Result := 'Leerer Parameter'; // division durch 0 erkannt on E: EZeroDivide do Result := 'Division durch Null (0)'; // übergebener parameter ist keine zahl on E: EConvertError do Result := 'Keine Zahl (NaN)'; // was gibt es sonst noch ??? on E: Exception do Result := '??? ' + E.Message; end; end;
Das Beispiel... ![]() Der nächste Schritt Im nächsten Teil dieses Tutorials fangen wir mit der Erstellung einer Komponente an. Diese Komponente ermöglicht es uns das Aussehen von Fehlermeldungen zu beeinflussen oder gar komplett Kontext-abhängige Fehlerbehandlungen durchzuführen. Mal sehn was kommt... Tippfehler gefixt! FuckRacism
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |