Advanced Services | Exceptions |
Es läuft nicht immer alles so, wie es gedacht war. Diese banale Weisheit stimmt auch für das Programmieren. Es passieren die unterschiedlichsten Fehler, für die einen ist man selbst verantwortlich, für andere wiederum nicht, die einen sind relativ harmlos, andere jedoch ziemlich katastrophal. Da man im Amerikanischen in diesem Zusammenhang "to throw an Error or an Exception" sagt, hat sich mittlerweile auch im Deutschen die Sprechweise "einen Fehler oder eine Ausnahme werfen" eingebürgert. C# hat für Fehler eigene Fehlerklassen eingeführt. Im Gegensatz zu Java gibt es weder eine Klasse Error noch eine Klasse Throwable (es gibt zwar in Microsoft.Build.Tasks eine versiegelte Klasse Error, diese hat aber nichts mit der Klasse Exception und ihrer Unterklassen zu tun). Alle Fehler, bzw. Ausnahmen sind also Unterklassen von Exception aus dem using System.
Im Gegensatz zu Java erzwingt der Compiler nie eine Fehlerbehandlung. Die Fehlerbehandlung obliegt allein dem Programmierer. So etwas wie "checked exceptions", also Code, bei dem Compiler sinngemäß meldet "Hier mußt du eine Fehlerbehandlung machen", gibt es nicht. Macht man kene Fehlerbehandlung, so treten die Fehler eben zur Laufzeit auf. Gut, wenn sie gleich bei den ersten Tests auftreten, schlecht, wenn sie später auftreten. Hierzu gleich ein einfaches Beispiel.
Das folgende Progrämmchen wirft (natürlich) eine Ausnahme.
class Exceptions01 { static void Main(string[] args) { String st = "keine Zahl"; int zahl = Convert.ToInt32(st); Console.WriteLine(zahl); }
Aber eben erst zur Laufzeit.
Glücklicherweise bekommen wir in den meisten Fällen detaillierte Informationen auf der Konsole.
Name der Fehlerklasse: System.FormatException.
static void Main(string[] args) { int[] arr = { 1, 2, 3 }; int i; for (i = 0; i < arr.Length; i++) arr[i]++; Console.WriteLine(arr[i]); }
Name der Fehlerklasse: System.IndexOutOfRangeException
Ein beliebter Fehler. Nach der Schleife hat i den Wert arr.Length, aber der Feldindex arr.Length existiert nicht. Ein Blick in die API zeigt uns, daß sowohl FormatException wie auch IndexOutOfRangeException direkte Unterklasse von SystemException sind.
Mit der statischen Methode Sleep() aus der Klasse Thread können wir den Programmablauf für 2 Sekunden unterbrechen.
using System; using System.Threading; namespace exceptions { class Exceptions { static void Main(string[] args) { Console.WriteLine("Schlafe mal eben fuer zwei Sekunden") ; Thread.Sleep(2000); Console.WriteLine("Bin wieder aufgewacht"); } } }
Hier bekommen wir keinen Laufzeitfehler. Trotzdem sollte man vorsichtig sein. Auch diese Methode kann nämlich einen Fehler werfen, und zwar ArgumentOutOfRangeException (was bei einem festen positiven Wert natürlich nicht passieren kann). Doch wie erfährt man von dieser Exception?
Im Zusammenhang mit der Arbeit mit Dateien können eine ganze Reihe von Exceptions auftreten. Das letzte Beispiel geht ja schon in diese Richtung.
static void Main(string[] args) { String text = File.ReadAllText(""); Console.WriteLine(text); }
In der obigen Situation verzeichnet die API nicht weniger als 9 verschiedene Exceptions.
Wie man diese Exceptions behandeln kann werden wir gleich im nächsten Kapitel erfahren. Zu jedem Beispiel werden wir
eine korrigierte Fassung anlegen, die die Exceptions berücksichtigt.
es mag auf den ersten Blick erstaunen, aber auch Propterties können Exceptions werfen. Da der Compiler aber Properties mit Hilfe von Methoden realisiert ist es nicht so verwunderlich.
static void Main() { DriveInfo di = new DriveInfo("x:\\"); Console.WriteLine(di.AvailableFreeSpace); // kann IOException werfen Console.WriteLine(di.Name); // wirft keine Exceptions Console.WriteLine(di.VolumeLabel ); // kann IOException, SecurityException oder UnauthorizedAccessException werfen }