Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 7 Fehlerbehandlung und Debugging
Pfeil 7.1 Laufzeitfehler behandeln
Pfeil 7.1.1 Laufzeitfehler erkennen
Pfeil 7.1.2 Die »try...catch«-Anweisung
Pfeil 7.1.3 Behandlung mehrerer Exceptions
Pfeil 7.1.4 Die Reihenfolge der »catch«-Zweige
Pfeil 7.1.5 Ausnahmen in einer Methodenaufrufkette
Pfeil 7.1.6 Ausnahmen werfen oder weiterleiten
Pfeil 7.1.7 Die »finally«-Anweisung
Pfeil 7.1.8 Die Klasse »Exception«
Pfeil 7.1.9 Benutzerdefinierte Ausnahmen
Pfeil 7.2 Debuggen mit Programmcode
Pfeil 7.2.1 Einführung
Pfeil 7.2.2 Die Klasse »Debug«
Pfeil 7.2.3 Die Klasse »Trace«
Pfeil 7.2.4 Bedingte Kompilierung
Pfeil 7.3 Fehlersuche mit Visual Studio 2012
Pfeil 7.3.1 Debuggen im Haltemodus
Pfeil 7.3.2 Das »Direktfenster«
Pfeil 7.3.3 Weitere Alternativen, um Variableninhalte zu prüfen

Rheinwerk Computing - Zum Seitenanfang

7.2 Debuggen mit ProgrammcodeZur nächsten Überschrift


Rheinwerk Computing - Zum Seitenanfang

7.2.1 EinführungZur nächsten ÜberschriftZur vorigen Überschrift

In Abschnitt 7.1 haben wir uns mit Fehlern beschäftigt, die nach der erfolgreichen Kompilierung zur Laufzeit auftreten können und, falls sie nicht behandelt werden, unweigerlich zum Absturz des Programms führen. Vielleicht noch schlimmer sind Fehler, die weder vom Compiler erkannt werden noch einen Laufzeitfehler verursachen. Es sind die logischen Fehler, aus denen ein falsches oder zumindest unerwartetes Ergebnis resultiert. Um logische Fehler aufzuspüren, muss die Anwendung unter Zuhilfenahme des integrierten Debuggers untersucht werden.

Das .NET Framework stellt Ihnen eine Reihe von Hilfsmitteln zur Verfügung, um den Programmcode zu debuggen. Die Spanne reicht von der einfachen Ausgabe von Meldungen im Ausgabe-Fenster bis zur Umleitung der Meldungen in eine Datei oder das Windows-Ereignisprotokoll. Dabei können Sie das Laufzeitverhalten einer Anwendung sowohl mit Programmcode als auch mit der Unterstützung von Visual Studio überprüfen. Wir werden in den nächsten Abschnitten auf alle Debugging-Techniken eingehen.


Rheinwerk Computing - Zum Seitenanfang

7.2.2 Die Klasse »Debug«Zur nächsten ÜberschriftZur vorigen Überschrift

In den vorangegangenen Beispielen haben wir uns sehr häufig eines Kommandos bedient, um beispielsweise den Inhalt von Variablen zu überprüfen. Es war die Methode WriteLine der Klasse Console:

int value = 12;
Console.WriteLine(value);

Diese Technik hat zur Folge, dass die Ausgabe an der Konsole unübersichtlich wird und zwischen den erforderlichen Programminformationen immer wieder Informationen zu finden sind, die im Grunde genommen nur dazu dienen, die Entwicklung zu unterstützen. Bevor ein solches Programm an den Kunden ausgeliefert wird, müssen die Testausgaben aus dem Programmcode gelöscht werden.

Die Entwicklungsumgebung bietet uns eine bessere Alternative an. Dazu wird die Ausgabe nicht in das Konsolenfenster geschrieben, sondern in das Ausgabe-Fenster von Visual Studio. Standardmäßig wird dieses Fenster am unteren Rand der Entwicklungsumgebung angezeigt. Sie können es sich anzeigen lassen, indem Sie im Menü Ansicht den Menüpunkt Ausgabe wählen.

Abbildung

Abbildung 7.6 Das Fenster »Ausgabe«

Sie haben dieses Fenster wahrscheinlich schon häufig gesehen und aufmerksam seinen Inhalt gelesen, denn bei jeder Kompilierung werden hier Informationen ausgegeben, beispielsweise ob die Kompilierung fehlerfrei war. Das Ausgabe-Fenster zeigt uns aber nicht nur Informationen an, die der Compiler hineinschreibt, wir können auch eigene Meldungen in dieses Fenster umleiten.

Eine Debug-Information in das Ausgabe-Fenster zu schreiben, ist genauso einfach wie die Ausgabe an der Konsole. Wir müssen nur die Anweisung

Console.WriteLine("...");

durch

Debug.WriteLine("...");

ersetzen. Debug ist eine nicht ableitbare Klasse des Namespaces System.Diagnostics, die ausschließlich statische Member bereitstellt.

Die Methode Debug.WriteLine unterscheidet sich von der Methode Console.WriteLine dahingehend, dass sie keine Formatierungsmöglichkeiten erlaubt. Um mehrere Informationen in einer gemeinsamen Zeichenfolge unterzubringen, müssen Sie daher den Verknüpfungsoperator »+« benutzen:

Debug.WriteLine("Inhalt von value = " +  value);

Programmablaufinformationen anzeigen

Debug.WriteLine ist mehrfach überladen und kann ein Argument vom Typ string oder object entgegennehmen. Eine parameterlose Überladung gibt es nicht.

public static void WriteLine(object value);
public static void WriteLine(string message);

Optional können wir auch ein zweites string-Argument übergeben, das eine detaillierte Beschreibung bereitstellt, die vor der eigentlichen Debug-Information ausgegeben wird.

public static void WriteLine(object value, string category);
public static void WriteLine(string message, string category);

Sehen wir uns das an einem Beispiel an. Die Anweisung

Debug.WriteLine("Inhalt von value = " + value, "Variable value");

wird in das Ausgabe-Fenster

Variable value: Inhalt von value = 34

schreiben – vorausgesetzt, der Inhalt von value ist 34.

Neben WriteLine sind in der Klasse Debug noch weitere Methoden zur Ausgabe von Informationen definiert. Tabelle 7.2 gibt darüber Auskunft.

Tabelle 7.2 Ausgabemethoden der Klasse »Debug«

Methode Beschreibung

Write

Schreibt Debug-Informationen ohne Zeilenumbruch.

WriteLine

Schreibt Debug-Informationen mit Zeilenumbruch.

WriteIf

Schreibt Debug-Informationen ohne Zeilenumbruch, wenn eine bestimmte Bedingung erfüllt ist.

WriteLineIf

Schreibt Debug-Informationen mit Zeilenumbruch, wenn eine bestimmte Bedingung erfüllt ist.

Die beiden zuletzt aufgeführten Methoden WriteIf und WriteLineIf schreiben nur dann Debug-Informationen, wenn eine vordefinierte Bedingung erfüllt ist. Damit lässt sich der Programmcode übersichtlicher gestalten. Beide Methoden sind genauso überladen wie Write bzw. WriteLine, erwarten jedoch im ersten Parameter zusätzlich einen booleschen Wert, z. B.:

public static void WriteIf(bool condition, string message);

Verdeutlichen wir uns den Einsatz an einem Beispiel. Um den Inhalt des Feldes value zu testen, könnten wir in herkömmlicher Weise codieren:

if (value == 77)
Debug.WriteLine("Inhalt von value ist 77");

Mit WriteLineIf wird daraus eine Codezeile:

Debug.WriteLineIf(value == 77, "Inhalt von value ist 77");

Einrücken der Ausgabeinformation

Die Klasse Debug stellt uns Eigenschaften und Methoden zur Verfügung, um die Debug-Ausgaben einzurücken. Mit der Methode Indent wird die Einzugsebene um eins erhöht, mit Unindent um eins verringert. Standardmäßig beschreibt eine Einzugsebene vier Leerzeichen. Mit der Eigenschaft IndentSize kann ein anderer Wert bestimmt werden. IndentLevel erlaubt, eine bestimmte Einzugsebene festzulegen, ohne Indent mehrfach aufrufen zu müssen. An einem Beispiel wollen wir uns noch die Auswirkungen ansehen.

Debug.WriteLine("Ausgabe 1");
Debug.Indent();
Debug.WriteLine("Ausgabe 2");
Debug.IndentLevel = 3;
Debug.WriteLine("Ausgabe 3");
Debug.Unindent();
Debug.WriteLine("Ausgabe 4");
Debug.IndentSize = 2;
Debug.IndentLevel = 1;
Debug.WriteLine("Ausgabe 5");

Listing 7.17 Strukturierte Ausgabe im »Ausgabe«-Fenster

Der Code führt zu folgender Ausgabe:

Ausgabe 1
Ausgabe 2
Ausgabe 3
Ausgabe 4
Ausgabe 5

Die Methode »Assert«

Mit der Methode Assert können Sie eine Annahme prüfen, um beispielsweise unzulässige Zustände festzustellen. Die Methode zeigt eine Fehlermeldung an, wenn ein Ausdruck mit false ausgewertet wird.

Debug.Assert(value >= 0, "value ist negativ");

Hat die Eigenschaft value einen Wert, der kleiner 0 ist, erscheint auf dem Bildschirm die in Abbildung 7.7 gezeigte Nachricht.

Abbildung

Abbildung 7.7 Die Meldung der Methode »Debug.Assert«

Das Dialogfenster enthält neben der dem zweiten Parameter übergebenen Zeichenfolge auch Informationen darüber, in welcher Klasse und welcher Methode der Assertionsfehler aufgetreten ist.


Rheinwerk Computing - Zum Seitenanfang

7.2.3 Die Klasse »Trace«Zur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse Trace unterscheidet sich in der Liste ihrer Eigenschaften und Methoden nicht von Debug. Dennoch gibt es einen Unterschied, der sich nur bei einem Wechsel der Build-Konfiguration zwischen Release und Debug bemerkbar macht (siehe Abbildung 7.8).

Abbildung

Abbildung 7.8 Die Einstellung der Debug/Release-Build-Konfiguration

Die Debug/Release-Konfiguration

Standardmäßig ist bei jedem neuen Projekt die Konfiguration Debug eingestellt. Anweisungen, die auf den Klassen Debug oder Trace basieren, werden dann grundsätzlich immer bearbeitet. Wird jedoch die Konfiguration Release gewählt, ignoriert der C#-Compiler Aufrufe der Klasse Debug, während Aufrufe auf Trace weiterhin bearbeitet werden.

Das ist aber noch nicht das Wesentlichste. Viel wichtiger ist die Tatsache, dass Aufrufe auf Trace kompiliert werden – unabhängig davon, ob Sie die Konfiguration Debug oder Release eingestellt haben. Viele Trace-Anweisungen vergrößern deshalb auch das DLL- bzw. EXE-Kompilat. Andererseits hat der Entwickler hier auch eine einfache Möglichkeit, bestimmte Zustände zu protokollieren, die sich zur Laufzeit einstellen und geprüft werden müssen.

Unterhalb des Verzeichnisses, in dem sich die Quellcodedateien befinden, legt die Entwicklungsumgebung das Verzeichnis \bin an, dem selbst je nach eingestellter Build-Konfiguration die beiden Verzeichnisse \Debug und \Release untergeordnet sind. Abhängig von der Konfigurationseinstellung wird das Kompilat der ausführbaren Datei in eines dieser beiden Unterverzeichnisse gespeichert.

Debug-Informationen, die beim Kompilieren generiert werden, sind in einer Datei mit der Dateierweiterung .pdb im Verzeichnis gespeichert. Der Debugger nutzt die darin enthaltenen Informationen, um Variablennamen und andere Informationen während des Debuggens in einem sinnvollen Format anzuzeigen.


Rheinwerk Computing - Zum Seitenanfang

7.2.4 Bedingte KompilierungZur nächsten ÜberschriftZur vorigen Überschrift

Die bedingte Kompilierung ermöglicht es, Codeabschnitte oder Methoden nur dann zu kompilieren, wenn ein bestimmtes Symbol definiert ist. Üblicherweise werden bedingte Codeabschnitte dazu benutzt, während der Entwicklungsphase den Zustand der Anwendung zur Laufzeit zu testen. Bevor ein Release-Build der Anwendung erstellt wird, wird das Symbol entfernt. Die Abschnitte, deren Code als bedingt kompilierbar gekennzeichnet ist, werden dann nicht kompiliert.

Der folgende Code zeigt ein Beispiel für bedingte Kompilierung:

#define MYDEBUG
using System;
class Program {
static void Main(string[] args) {
#if(MYDEBUG)
Console.WriteLine("In der #if-Anweisung");
#elif(TEST)
Console.WriteLine("In der #elif-Anweisung");
#endif
}
}

Mit der Präprozessordirektive #define wird das Symbol MYDEBUG definiert. Symbole werden immer vor der ersten Anweisung festgelegt, die selbst keine #define-Präprozessordirektive ist. Werte können den Symbolen nicht zugewiesen werden. Die Präprozessordirektive gilt nur in der Quellcodedatei, in der sie definiert ist, und wird nicht mit einem Semikolon abgeschlossen.

Mit #if oder #elif wird das Vorhandensein des angegebenen Symbols getestet. Ist das Symbol definiert, liefert die Prüfung das Ergebnis true, und der Code wird ausgeführt. #elif ist die Kurzschreibweise für die beiden Anweisungen #else und #if. Da im Beispielcode kein Symbol namens TEST definiert ist, wird die Ausgabe wie folgt lauten:

In der #if-Anweisung

Standardmäßig sind in C#-Projekten die beiden Symbole DEBUG und TRACE vordefiniert. Diese Vorgabe ist im Projekteigenschaftsfenster eingetragen (siehe Abbildung 7.9) und hat anwendungsweite Gültigkeit. Das Projekteigenschaftsfenster öffnen Sie, indem Sie im Projektmappen-Explorer den Knoten Properties doppelt anklicken. Sie können die Symbole löschen oder auch weitere hinzufügen, die ihrerseits alle durch ein Semikolon voneinander getrennt werden müssen.

Das Projekteigenschaftsfenster bietet darüber hinaus den Vorteil, dass sich die Symbole einer bestimmten Build-Konfiguration zuordnen lassen. Wählen Sie in der Dropdown-Liste Konfiguration die Build-Konfiguration aus, für welche die unter Bedingte Kompilierungskonstanten angegebenen Symbole gültig sein sollen. Wenn Sie beispielsweise keine #define-Präprozessordirektive im Code angeben, dafür aber der Debug-Konfiguration das Symbol DEBUG zugeordnet haben, wird der in #if - #endif eingeschlossene Code im Debug-Build mitkompiliert, im Release-Build jedoch nicht.

Die im Projekteigenschaftsfenster definierten Konstanten gelten projektweit. Um in einer einzelnen Codedatei die Wirkung eines Symbols aufzuheben, müssen Sie das Symbol hinter der #undef-Direktive angeben.

Abbildung

Abbildung 7.9 Festlegung der Symbole im Projekteigenschaftsfenster

Bedingte Kompilierung mit dem Attribut »Conditional«

Häufig ist es wünschenswert, eine komplette Methode als bedingt zu kompilierende Methode zu kennzeichnen. Hier hilft Ihnen .NET mit dem Attribut Conditional aus dem Namespace System.Diagnostics weiter.

Und wieder muss ich Attribute erwähnen, ohne dass wir uns bisher diesem Thema gewidmet haben. Ich weiß, es ist nicht immer schön, auf Features zuzugreifen, die noch nicht behandelt worden sind. Ich mag das bei den Büchern, die ich lese, auch nicht. Nur leider lässt es sich nicht immer vermeiden, weil die Zahnrädchen des .NET Frameworks so komplex ineinandergreifen. Also noch einmal der Hinweis: In Kapitel 10 werde ich Ihnen alles Wissenswerte zu den Attributen erzählen.

Damit eine komplette Methode als bedingt kompilierbar gekennzeichnet wird, muss das Conditional-Attribut (wie im folgenden Beispiel gezeigt) vor dem Methodenkopf in eckigen Klammern angegeben werden. In den runden Klammern wird das Symbol als Zeichenfolge genannt:

[Conditional("DEBUG")]
public void ConditionalTest()
{
[...]
}

Listing 7.18 Methode mit dem Attribut »Conditional«

Die Methode ConditionalTest wird jetzt nur dann kompiliert, wenn das Symbol DEBUG gesetzt ist. Sie können auch mehrere Attribute mit unterschiedlichen Symbolen angeben. Kann eines der Symbole ausgewertet werden, wird die Methode ausgeführt. Anders als bedingter Code, der durch #if - #endif eingeschlossen ist, wird eine Methode, der das Conditional-Attribut angeheftet ist, immer kompiliert.

Sie müssen beachten, dass eine Methode mit einem Conditional-Attribut immer den Rückgabetyp void haben muss und nicht mit dem Modifizierer override gekennzeichnet sein darf.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2013
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern