Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Exception Handling in C#

Geschrieben von: Christoph Wille
Kategorie: C#

Ich nehme an, daß jeder VBScript Programmierer schon mindestens einmal die sehr eingeschränkten Möglichkeiten der Fehlerbehandlung in das Land des Pfeffers gewunschen hat - ein einfaches On Error Resume Next ist nun wirklich nicht gerade das, was man unter zeitgemäßer Fehlerbehandlung verstehen sollte. Aber man mußte damit leben, immer Err.Number auszulesen, oder zu riskieren, daß der Benutzer einen nicht abgefangenen Fehler zu Gesicht bekommt.

Die gute Nachricht ist, daß das Microsoft .NET Framework für alle Programmiersprachen ein einheitliches Fehlermangagement zur Verfügung stellt: Exceptions ("Ausnahmen"). Dadurch, daß es ein fixer Teil des Frameworks ist, können Exceptions in einer Komponente ausgelöst, und im aufrufenden Programm auch abgefangen werden - und das, wie immer im Framework, über die Grenzen der Programmiersprachen hinweg. Das bedeutet auch das Ende für die von vielen "heißgeliebten" 8000er Fehlermeldungen.

Voraussetzung um den Sourcecode dieses Artikels verwenden zu können ist eine Installation des Microsoft .NET Framework SDK's auf einem Webserver. Weiters setze ich voraus, daß der Leser bereits eine Programmiersprache beherrscht - deshalb ist die Information auch in sehr komprimierter Form gehalten.

Minimales Exception Handling

Bevor wir uns die Befehle für das Exception Handling anschauen, möchte ich ein nettes kleines Beispiel produzieren, das uns mit Exceptions versorgt. Schauen wir uns dazu ein harmlos aussehendes Programm an (requestget.aspx).

<% @Page Language="C#" %>
<%
string strReqItem = Request.QueryString.Get("ReqItem");
Response.Write(strReqItem);
%>

Wenn man dieses Programm ohne Querystring aufruft, bekommt man keine Ausgabe am Bildschirm. Übergibt man einen korrekten Querystring, wird der Wert für ReqItem ausgegeben, so zum Beispiel:

http://localhost/RequestGet.aspx?ReqItem=Hello+World

Auch wenn man sich sehr anstrengt, wird das keine Exception auslösen. Wie kommen wir also zu einer Exception? Indem wir den übergebenen Wert auf einen int umwandeln wollen (requestget_cast2int.aspx):

<% @Page Language="C#" %>
<%
string strReqItem = Request.QueryString.Get("ReqItem");
int nReqItem = Int32.Parse(strReqItem);
Response.Write(nReqItem.ToString());
%>

Die Sache hat nicht nur einen, sondern gleich 2 Haken: wenn wir keinen Querystring übergeben, hat strReqItem den Wert null - und mit einem null-Objekt macht man in der Parse Methode keinen Staat - und man bekommt folgenden Fehler:

Das ist die ArgumentNullException weil kein Wert übergeben wurde. Wenn man einen Wert übergibt, der Wert allerdings mit ToInt32 nicht auf int umgewandelt werden kann, dann steht einem die FormatException ins Haus - der Haken numero due. Auslösen kann man diesen Fehler mit folgender URL:

http://localhost/RequestGet_Cast2Int.aspx?ReqItem=NaN

So - jetzt haben wir unsere Exception. Uns bleibt sozusagen "nur noch" die Aufgabe, die Exception ordnungsgemäß zu behandeln. Und dazu stellt uns C# das try-catch-finally Konstrukt zur Verfügung. Wer C++ programmiert hat, dem wird das sehr bekannt vorkommen, da es SEH (structured exception handling) nachempfunden ist. Das Gute daran - es ist sehr einfach es anzuwenden.

Es gibt gute und schlechte Beispiele, und ich möchte jetzt ausnahmsweise ein "schlechtes" aus dem Ärmel zaubern (try-one.aspx). Das ist das minimale Beispiel, wie man Exception Handling vielleicht doch nicht implementieren soll:

<% @Page Language="C#" %>
<%
string strReqItem = Request.QueryString.Get("ReqItem");
try
{
	int nReqItem = Int32.Parse(strReqItem);s
}
// entweder catch oder finally muß nach try kommen
finally
{
}
%>

Warum ist das ein schlechtes Beispiel? Nun ja, es kompiliert und läuft zwar, der Haken ist allerdings das finally Statement: dieses wird nach try immer aufgerufen, ob eine Exception ausgelöst wurde oder nicht (dort sollte also der Code hinein, der in beiden Fällen ausgeführt werden soll). Das ist noch nicht das Schlechte an der Sache - das Problem ist, daß "niemand" die Exceptions abfängt, die wir schon diskutiert haben. Der "Niemand" ist aber ASP.NET - immer wenn eine unbehandelte Exception auftritt, bekommt man wieder die ASP.NET Fehlermeldung wie schon im vorangegangenen Bild gezeigt. Also nicht unbedingt die leise Fehlerbehandlung, die wir im Sinne hatten.

Daher sollte man anstatt des finally Statements für minimales Exception Handling doch eher zuerst zu catch greifen.

Das catch Statement

Also kümmern wir uns um die Exceptions, und zwar diesmal "leise" (try-two.aspx):

<% @Page Language="C#" %>
<%
string strReqItem = Request.QueryString.Get("ReqItem");
try
{
	int nReqItem = Int32.Parse(strReqItem);
}
catch
{
}
%>

Wenn jetzt ein Fehler auftritt, wird er geschluckt, weil unser catch Block keine Fehlermeldung ausgibt. Das, was dieses Beispiel imitiert ist die Verwendung von On Error Resume Next ohne jemals den Error Code auszulesen.

Das folgende leicht modifizierte Beispiel fängt die Exception im catch Statement ab, und der Fehlertext wird zum Benutzer geschickt - die minimale Variante dessen, was die ASP.NET Error Page unter anderem auch macht:

<% @Page Language="C#" %>
<%
string strReqItem = Request.QueryString.Get("ReqItem");
try
{
	int nReqItem = Int32.Parse(strReqItem);
}
catch(Exception e)
{
	Response.Write(e.ToString());
}
%>

Dies ist natürlich auch nicht im Sinne des Erfinders - man sollte sinnvolle Dinge mit Exceptions machen, und sei es "nur", dem Benutzer eine sinnvolle Fehlermeldung zu präsentieren, was im nächsten Abschnitt beschrieben wird.

Abfrage verschiedener Exceptions

Das Schöne am catch Statement ist, daß man es mehrmals verwenden darf - um Exceptions verschiedenen Typs unterschiedlich zu behandeln. Für unser Beispiel wäre das, zuerst zu überprüfen ob etwas übergeben wurde, danach ob die Konvertierung funktioniert hat, und schließlich werden noch etwaige andere Fehler abgefangen (try-three.aspx):

<% @Page Language="C#" %>
<%
string strReqItem = Request.QueryString.Get("ReqItem");
int nReqItem = 0;
try
{
	nReqItem = Int32.Parse(strReqItem);
}
catch(ArgumentNullException e)
{
	Response.Write("Sie müssen den Parameter <b>ReqItem</b> angeben!");
}
catch(FormatException e)
{
	Response.Write("Der Parameter <b>ReqItem</b> muß eine Zahl sein!");
}
catch(Exception e)
{
	Response.Write("Fehler aufgetreten: " + e.ToString());
}
finally
{
	Response.Write("<br>Fehler oder nicht - hier sind wir!");
}
%>

Bevor die Frage auftaucht, ob man die Reihenfolge der catch Statements umdrehen kann, möchte ich sie auch gleich beantworten - ja und nein. Man darf zwar ArgumentNullException und FormatException tauschen, allerdings kann man Exception vor keine der beiden anderen reihen. Der Grund dafür ist, daß die allgemeine Exception Klasse alle spezielleren (in unserem Fall die ersten beiden) überlagert. Allerdings wird man niemals diesen Fehler machen - der Compiler beschwert sich heftigst, wenn man die Reihenfolge falsch hat.

Wie dieses Beispiel zeigt, kann man mit Exception Handling den Sourcecode deutlich fehlertoleranter gestalten. Obwohl ich nur eine Zeile im try Block hatte, ist man natürlich auf keinerlei Limit an Code im try Block eingeschränkt. Und wie man den Fehler im Endeffekt behandelt, bleibt dem Anwendungsfall überlassen.

Schlußbemerkung

Natürlich kann man nicht nur Exceptions abfangen, sondern Exceptions selbst werfen (mit dem throw Statement). Dabei muß man nicht auf vorgefertige vom Framework zur Verügung gestellte zurückgreifen, man kann auch eigene, spezialisierte, erstellen und verwenden.

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Das using Schlüsselwort
Dateien umbenennen
Dateiupload mit ASP.NET
Der ODBC .NET Data Provider
Deutsche Personalausweisnummern verifizieren
Die Hashtable Klasse
Directory Browsing a la .NET
Ein Touch-Utility in C#
Exception Handling in Visual Basic.NET
Formularbasierte Authentifizierung in fünf Minuten
Index Server Abfragen per Web Service
Online File Management System mit ASP.NET und C# - Teil 1
On-the-fly Generierung von Graphiken
Regex'en zu Assemblies kompilieren
Scrapen von Webseiten
Sichere Konvertierungen von Referenztypen
Webseiten automatisiert scrapen, Teil 2
WHOIS Abfragen a la .NET

Links zu anderen Sites

Die aspDEdotnet Liste
Presenting C#

Wenn Sie jetzt Fragen haben...

Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten.

Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist.

Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.

 

Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.