C# Debugging - Tutorials.de
C# Debugging - Tutorials.de
C# Debugging - Tutorials.de
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
1. Vorwort<br />
2. Einleitung<br />
<strong>C#</strong><br />
<strong>Debugging</strong><br />
3. Entwicklungsumgebung<br />
4. Grundlagen<br />
5. <strong>Debugging</strong> (Ver. 1.03)<br />
6. Objektorientierung<br />
7. Fehlerbehandlung<br />
by Erik Bartmann<br />
1
<strong>Debugging</strong>............................................................................................................3<br />
2<br />
Debuggen mit Haltepunkten ............................................................................4<br />
Haltepunkt setzen.........................................................................................4<br />
Haltepunkt löschen.......................................................................................5<br />
In einen Haltepunkt laufen...........................................................................5<br />
Daten inspizieren .........................................................................................6<br />
Einzelschritt ...............................................................................................13<br />
Debuggen ohne Haltepunkt(e) .......................................................................18<br />
Ausführen bis Cursor .................................................................................18<br />
Arbeiten mit <strong>de</strong>r Klasse „Debug“ ..............................................................19<br />
Fehlermeldung ...............................................................................................26<br />
Source-Co<strong>de</strong> im Haltezustand bearbeiten..................................................26<br />
Bedingte Kompilierung..................................................................................26<br />
Attribut Conditional...................................................................................30<br />
Compilermeldungen.......................................................................................31<br />
Deaktivieren / Aktivieren...........................................................................31<br />
Eigene Meldungen erstellen.......................................................................34
<strong>Debugging</strong><br />
Fehlersuche hat etwas mit Spurensuche zu tun. Wir müssen einem Umstand auf<br />
die Schliche kommen, <strong>de</strong>r unser Programm nicht wie beabsichtigt laufen lässt.<br />
Syntaktische Fehler, die sich schon zur Entwicklungszeit zu erkennen geben,<br />
sind natürlich einfacher ausfindig zu machen, als logische Fehler. Woher soll<br />
das Programm auch wissen, dass es an<strong>de</strong>rs laufen soll, als <strong>de</strong>r Programmierer es<br />
vorgesehen hat? Einer Variablen, <strong>de</strong>r ein falscher Wert zugewiesen wur<strong>de</strong>,<br />
schleppt sich durch die ganze Applikation. Eine fehlerhafte Formel lässt einem<br />
die Haare zu Berge stehen.<br />
Die Entwicklungsumgebung von Visual <strong>C#</strong> 2005 Express Edition bietet <strong>de</strong>m<br />
Entwickler eine Möglichkeit, <strong>de</strong>n o<strong>de</strong>r die Fehler zu lokalisieren. Vergleichbar<br />
mit <strong>de</strong>r Programmunterbrechnung beim Auftreten einer Exception zur Laufzeit,<br />
können wir das Programm kontrolliert an fast je<strong>de</strong>r beliebigen Stelle im Co<strong>de</strong><br />
anhalten. Wie das funktioniert, habe ich Ihnen im Kapitel über Arrays schon<br />
kurz gezeigt. Dort haben wir uns die Array-Inhalte nach Setzten eines so<br />
genannten Haltepunktes, auch Breakpoint genannt, angeschaut. Wur<strong>de</strong> die<br />
Programmausführung an einer Stelle unterbrochen, können wir uns<br />
Variableninhalte anschauen und ihnen sogar manuell Werte zuweisen, die nicht<br />
per Anweisung im Source-Co<strong>de</strong> existieren. Auf diese Weise gestaltet sich das<br />
Debuggen sehr flexibel. Sie können, ohne das Programm erneut zu starten und<br />
es am Breakpoint anzuhalten, Variableninhalte modifizieren und die<br />
3
Programmfortsetzung <strong>de</strong>n eigenen Wünschen anpassen. Nehmen wir an, dass<br />
einer Variablen ein bestimmter Wert zugewiesen wur<strong>de</strong>, um sie in <strong>de</strong>r nächsten<br />
Zeile in einer Berechnung zu verwen<strong>de</strong>n. Lei<strong>de</strong>r entspricht das Ergebnis nicht<br />
unseren Erwartungen. Den Breakpoint haben wir hinter die Ausgabe <strong>de</strong>s<br />
Ergebnisses an die Konsole gesetzt. Jetzt starten Sie die Anwendung und lassen<br />
sich das Ergebnis anzeigen. Sie modifizieren die Variable und setzten die<br />
Programmzeiger in die Zeile, in <strong>de</strong>r die Berechnung stattfin<strong>de</strong>t. Wird das<br />
Programm fortgesetzt, erfolgt die Berechnung mit <strong>de</strong>n neuen Daten. Ich wer<strong>de</strong><br />
Ihnen die einzelnen Schritte auf je<strong>de</strong>n Fall an einem Beispiel erläutern.<br />
Debuggen mit Haltepunkten<br />
Wie schon mehrfach erwähnt, müssen Sie zur Programmunterbrechung einen<br />
Haltepunkt an einer Stelle Ihres Source-Co<strong>de</strong>s setzten. Starten Sie das<br />
Programm z.B. mit , stoppt die Ausführung genau am <strong>de</strong>finierten Haltepunkt.<br />
Haltepunkt setzen<br />
Um <strong>de</strong>r Entwicklungsumgebung einen Haltepunkt mitzuteilen, klicken Sie mit<br />
<strong>de</strong>r linken Maustaste in <strong>de</strong>r entsprechen<strong>de</strong>n Zeile auf <strong>de</strong>n linken grauen Rand<br />
im Editor.<br />
4
Der Haltepunkt wird durch einen roten Kreis gekennzeichnet, wobei sich die<br />
Hintergrundfarbe <strong>de</strong>r Co<strong>de</strong>-Zeile zusätzlich in Rot än<strong>de</strong>rt.<br />
Haltepunkt löschen<br />
Das Löschen eines Haltepunktes erfolgt auf die gleiche Weise wie das Setzen.<br />
Klicken Sie mit <strong>de</strong>r linken Maustaste auf <strong>de</strong>n roten Kreis, wird <strong>de</strong>r zuvor<br />
gesetzte Haltepunkt gelöscht.<br />
In einen Haltepunkt laufen<br />
Schauen wir uns <strong>de</strong>n Source-Co<strong>de</strong> aus Co<strong>de</strong> 1 genauer an. Der Haltepunkt ist in<br />
Zeile 16 gesetzt.<br />
Dotty: „Wenn wir das Programm starten und die Ausführung <strong>de</strong>n Haltepunkt<br />
erreicht, wird dann die Zeile noch ausgeführt?“<br />
Wird <strong>de</strong>r Haltepunkt erreicht, dann be<strong>de</strong>utet das, dass in dieser Zeile erst einmal<br />
die Programmausführung unterbrochen ist. Die Anweisung in <strong>de</strong>r betreffen<strong>de</strong>n<br />
Zeile wur<strong>de</strong> zu diesem Zeitpunkt noch nicht zur Ausführung gebracht. Doch<br />
schauen wir uns <strong>de</strong>n Editor nach <strong>de</strong>m Start <strong>de</strong>s Programms mit genauer an:<br />
5
Unsere Anwendung hat <strong>de</strong>n gesetzten Haltepunkt erreicht. Sie erkennen es am<br />
gelben Pfeil, <strong>de</strong>r sich im Moment vor <strong>de</strong>n roten Kreis gesetzt hat. Der Pfeil<br />
stellt <strong>de</strong>n Programmzeiger dar, <strong>de</strong>r auf die Zeile weist, die als nächste zur<br />
Ausführung gebracht wird. Zusätzlich ist die Anweisung in gelb hinterlegt.<br />
Daten inspizieren<br />
Wur<strong>de</strong> <strong>de</strong>r Haltepunkt erreicht, haben wir die Möglichkeit, auf diverse<br />
Programmdaten zuzugreifen. Im Fensterbereich, in <strong>de</strong>m sich die Fehlerliste<br />
befin<strong>de</strong>t, erscheit hinter einem zusätzlichen Reiter verborgen, ein neues Fenster<br />
mit <strong>de</strong>r Bezeichnung lokal. Sollten Sie das Fenster einmal geschlossen haben,<br />
so kann es über das Programm-Menü Debuggen|Fenster|Lokal angezeigt<br />
wer<strong>de</strong>n.<br />
Daten im Fenster „Lokal“ auswerten<br />
Abb. 1: Daten nach Erreichen von Haltepunkt inspizieren<br />
In diesem Fenster wird eine Liste mit 3 Spalten angezeigt.<br />
6
Spaltenbezeichnung Be<strong>de</strong>utung<br />
Name Angabe <strong>de</strong>s Variablennamen<br />
Wert Anzeige <strong>de</strong>s Wertes, mit <strong>de</strong>m die Variable initialisiert ist<br />
Typ Anzeige <strong>de</strong>s Datentyps <strong>de</strong>r Variablen<br />
Tab. 1: Spalten im Fenster Lokal<br />
Wir erkennen, dass die Liste zwei Einträge enthält und somit zwei Variablen<br />
zum Zeitpunkt <strong>de</strong>s Erreichens <strong>de</strong>s Haltepunktes existieren. Konzentrieren wir<br />
uns auf <strong>de</strong>n zweiten Eintrag, <strong>de</strong>r die Variable intWert1 enthält. Sie ist mit <strong>de</strong>m<br />
numerischen Wert 10 initialisiert und vom Datentyp int. Die Initialisierung<br />
erfolgte über die Anweisung in Zeile 14. Schauen wir uns das Konsolenfenster<br />
an, so sehen wir das Ergebnis <strong>de</strong>r Berechnung aus Zeile 15. Sollten Sie jetzt<br />
versucht sein, im Konsolenfenster die Taste zu drücken, so wird dies keine<br />
Auswirkung auf die Fortsetzung <strong>de</strong>s Programms haben, da die Ausführung<br />
angehalten wur<strong>de</strong> und Zeile 16 noch nicht erreicht ist.<br />
Dotty: „Wie können wir das Programm fortsetzen?“<br />
Aus <strong>de</strong>m jetzigen statischen Zustand gibt es unterschiedliche Möglichkeiten <strong>de</strong>r<br />
Fortführung:<br />
Taste Aktion Beschreibung<br />
Programmausführung<br />
fortsetzen<br />
Fortsetzten <strong>de</strong>r Programmausführung ab <strong>de</strong>m<br />
momentanen Haltepunkt bzw. ab Programmzeiger.<br />
Einzelschritt Fortsetzten <strong>de</strong>r Programmausführung ab <strong>de</strong>m<br />
momentanen Haltepunkt bzw. Programmzeiger. Die<br />
Ausführung stoppt vor <strong>de</strong>r nächsten Anweisung.<br />
Beinhaltet die momentane Anweisung einen<br />
Metho<strong>de</strong>naufruf, so wird in die Metho<strong>de</strong> gesprungen<br />
und vor <strong>de</strong>r ersten Anweisung angehalten.<br />
Prozedurschritt Fortsetzten <strong>de</strong>r Programmausführung ab <strong>de</strong>m<br />
momentanen Haltepunkt bzw. Programmzeiger. Die<br />
7
Ausführung stoppt vor <strong>de</strong>r nächsten Anweisung.<br />
Beinhaltet die momentane Anweisung einen<br />
Metho<strong>de</strong>naufruf, so wird die Metho<strong>de</strong> in ihrer Gänze<br />
abgearbeitet und die Ausführung an <strong>de</strong>r Stelle<br />
angehalten, die <strong>de</strong>m Metho<strong>de</strong>naufruf unmittelbar folgt.<br />
+ Ausführen bis Fortsetzten <strong>de</strong>r Programmausführung ab <strong>de</strong>m<br />
Rücksprung<br />
momentanen Haltepunkt bzw. Programmzeiger.<br />
Befin<strong>de</strong>t sich <strong>de</strong>r Haltepunkt innerhalb einer Metho<strong>de</strong>,<br />
so wer<strong>de</strong>n die restlichen Zeilen abgearbeitet und die<br />
Ausführung an <strong>de</strong>r Stelle angehalten, die <strong>de</strong>m<br />
Metho<strong>de</strong>naufruf unmittelbar folgt.<br />
Tab. 2: Programmfortführung nach Haltepunkt<br />
Die Anzeige <strong>de</strong>r Variableninhalte im Fenster Lokal kann wahlweise in<br />
<strong>de</strong>zimaler (Standard) o<strong>de</strong>r hexa<strong>de</strong>zimaler Schreibweise erfolgen. Das<br />
Umschalten erfolgt über das Kontext-Menü <strong>de</strong>s Fensters. Wählen Sie dazu <strong>de</strong>n<br />
Eintrag „Hexa<strong>de</strong>zimale Anzeige“, <strong>de</strong>r daraufhin mit einem Haken versehen<br />
wird. Das Zurückschalten auf die <strong>de</strong>zimale Anzeige erfolgt in gleicher Weise<br />
über <strong>de</strong>nselben Eintrag; <strong>de</strong>r Haken wird entfernt.<br />
Daten über Tooltip anzeigen<br />
Die zweite Möglichkeit, Programminformationen bzw. Variableninhalte im<br />
Haltemodus anzuzeigen, ist durch das Verweilen <strong>de</strong>s Mauszeigers über einer<br />
Variablen gegeben.<br />
8
Ich habe <strong>de</strong>n Mauszeiger über <strong>de</strong>r Variablen intWert in Zeile 13 stehen<br />
lassen. Der Tooltip hat sich einen kurzen Augenblick später geöffnet und nennt<br />
uns <strong>de</strong>n Variablennamen inklusive Variableninhalt.<br />
Daten über Tooltip modifizieren<br />
Haben Sie sich auf diese Weise über <strong>de</strong>n Variableninhalt informiert, so ist es<br />
Ihnen sogar gestattet, <strong>de</strong>r Variablen einen neunen Wert zuzuweisen. Führen Sie<br />
folgen<strong>de</strong> Schritte aus:<br />
1. Fahren Sie dazu mit <strong>de</strong>m Mauszeiger in das Rechteck <strong>de</strong>s Tooltips hinein.<br />
Der Hintergrund wechselt, sofern Sie die Standardfarben verwen<strong>de</strong>n, von<br />
Hellgrau nach Dunkelgrau.<br />
2. Klicken Sie innerhalb <strong>de</strong>s Tooltips mit <strong>de</strong>r linken Maustaste. Vor <strong>de</strong>m<br />
momentanen Variablenwert erscheint ein blinken<strong>de</strong>r Cursor.<br />
3. Modifizieren Sie <strong>de</strong>n Wert nach Ihren Vorstellungen.<br />
4. Bestätigen Sie Ihre Eingabe mit <strong>de</strong>r Taste o<strong>de</strong>r verwerfen die<br />
Modifikation durch einen Klick mit <strong>de</strong>r linken Maustaste außerhalb <strong>de</strong>s<br />
Tooltips.<br />
Daten im Direktfenster<br />
Ist ein Haltepunkt erreicht und das Programm unterbrochen, so können Sie im<br />
Direktfenster z.B. folgen<strong>de</strong> Aktionen ausführen:<br />
♦ Anzeige von Variableninhalten<br />
♦ Auswerten und Ausführen von Ausdrücken<br />
♦ Aufrufen von Metho<strong>de</strong>n<br />
Die Anzeige <strong>de</strong>s Fensters erfolgt über das Programm-Menü<br />
Debuggen|Fenster|Direkt. Schauen Sie sich <strong>de</strong>n folgen<strong>de</strong>n Co<strong>de</strong> an:<br />
9
Die Variable intWert wird <strong>de</strong>klariert und mit einem Wert von 10 initialisiert.<br />
Der Haltepunkt befin<strong>de</strong>t sich in Zeile 13, in <strong>de</strong>r die Berechnung vorgenommen<br />
wer<strong>de</strong>n soll. Starten Sie das Programm über , stoppt das Programm kurz vor<br />
<strong>de</strong>r Multiplikation <strong>de</strong>r Variablen mit <strong>de</strong>m Wert 2. Gehen Sie jetzt in Ihr<br />
Direktfenster und geben nacheinan<strong>de</strong>r die gezeigten Eingaben ein.<br />
Abb. 2: Eingaben im Direktfenster<br />
Ihre erste Eingabe hat <strong>de</strong>n Inhalt <strong>de</strong>r Variablen intWert zur Anzeige<br />
gebracht. Dazu wird das Fragezeichen vor <strong>de</strong>n Variablennamen gesetzt und die<br />
Eingabe mit <strong>de</strong>r Taste bestätigt. Mit <strong>de</strong>r zweiten Eingabe haben Sie <strong>de</strong>r<br />
Variablen <strong>de</strong>n neuen Wert 90 zugewiesen. Lassen Sie das Programm z.B. mit<br />
weiterlaufen, so mel<strong>de</strong>t sich Ihr Konsolenfenster zurück. Das Ergebnis<br />
wur<strong>de</strong> mit <strong>de</strong>r von Ihnen neu initialisierten Variablen berechnet und lautet<br />
korrekter Weise 80 und nicht 20.<br />
Daten überwachen<br />
Kommen wir jetzt zu einem weiteren Fenster, dass uns <strong>Debugging</strong>-<br />
Informationen zur Verfügung stellt. Es ist das Überwachen-Fenster. Schauen<br />
wir uns dazu <strong>de</strong>n folgen<strong>de</strong>n simplen Source-Co<strong>de</strong> an:<br />
10
Nach <strong>de</strong>m Start mit stoppt die Ausführung aufgrund <strong>de</strong>s Haltepunktes in<br />
Zeile 12. Jetzt rufen wir über <strong>de</strong>n Menüpunkt Debuggen|Fenster|Überwachen<br />
das Überwachen-Fenster auf <strong>de</strong>n Schirm. Es enthält eine Liste aus 3 Spalten mit<br />
Informationen über Name, Wert und Typ. Da wir noch keine zu überwachen<strong>de</strong>n<br />
Informationen hinzugefügt haben, ist die Liste leer. Jetzt möchte ich <strong>de</strong>r Liste<br />
die Variable intWert1 hinzufügen, die im Laufe <strong>de</strong>s Programms überwacht<br />
wer<strong>de</strong>n soll. Folgen<strong>de</strong> Schritte sind notwendig:<br />
Erste Möglichkeit<br />
1. Programm mit starten<br />
2. Nach Erreichen <strong>de</strong>s Haltepunktes <strong>de</strong>n Mauszeiger über die Variable<br />
intWert1 platzieren.<br />
3. Das Kontext-Menü über die rechte Maustaste aufrufen.<br />
4. „Überwachung hinzufügen“ auswählen.<br />
Die Liste hat sich mit einem Eintrag gefüllt.<br />
11
Abb. 3: Überwachen Liste<br />
Zweite Möglichkeit<br />
1. Programm mit starten<br />
2. Nach Erreichen <strong>de</strong>s Haltepunktes einen Doppelklick mit <strong>de</strong>r linken<br />
Maustaste auf die Variable intWert1 absetzten. Die Variable wird<br />
dadurch im Editor markiert, was Sie am dunkelblauen Hintergrund erkennen<br />
können.<br />
3. Mit gedrückter linker Maustaste <strong>de</strong>n Namen <strong>de</strong>r Variablen in das Fenster<br />
ziehen und dort loslassen (Drag & Drop). Der Mauszeiger än<strong>de</strong>rt sich wie in<br />
<strong>de</strong>r folgen<strong>de</strong>n Abbildung gezeigt.<br />
Abb. 4: Überwachung per Drag & Drop hinzufügen<br />
Nach <strong>de</strong>m Loslassen <strong>de</strong>r linken Maustaste hat sich die Liste wie bei <strong>de</strong>r ersten<br />
Möglichkeit um einen Eintrag erweitert. Führen Sie <strong>de</strong>n Programmablauf im<br />
Einzelschrittverfahren mit fort, können Sie <strong>de</strong>n Än<strong>de</strong>rungen <strong>de</strong>s<br />
Variableninhaltes aufgrund <strong>de</strong>r Operationen in Zeile 13 bzw. 14 folgen. In je<strong>de</strong>r<br />
dieser bei<strong>de</strong>n Zeilen wird <strong>de</strong>r Wert <strong>de</strong>r Variablen um 1 erhöht. Möchten Sie<br />
weitere Variablen zur Überwachung hinzufügen, so verfahren Sie wie gera<strong>de</strong><br />
12
eschrieben. Das Entfernen einer Variablen aus <strong>de</strong>r Liste kann auf folgen<strong>de</strong><br />
Weisen erfolgen:<br />
Erste Möglichkeit<br />
1. Den gewünschten Listeneintrag mit linker Maustaste markieren.<br />
2. Die Taste drücken.<br />
Zweite Möglichkeit<br />
1. Den gewünschten Listeneintrag mit linker Maustaste markieren.<br />
2. Das Kontext-Menü über die rechte Maustaste aufrufen.<br />
3. „Überwachung löschen“ wählen.<br />
Die Anzeige <strong>de</strong>r Variableninhalte im Überwachungsfenster kann wahlweise in<br />
<strong>de</strong>zimaler (Standard) o<strong>de</strong>r hexa<strong>de</strong>zimaler Schreibweise erfolgen. Das<br />
Umschalten erfolgt über das Kontext-Menü <strong>de</strong>s Überwachungsfensters. Wählen<br />
Sie dazu <strong>de</strong>n Eintrag „Hexa<strong>de</strong>zimale Anzeige“, <strong>de</strong>r daraufhin mit einem Haken<br />
versehen wird. Das Zurückschalten auf die <strong>de</strong>zimale Anzeige erfolgt in gleicher<br />
Weise über <strong>de</strong>nselben Eintrag; <strong>de</strong>r Haken wird entfernt.<br />
Einzelschritt<br />
Ich möchte mit <strong>de</strong>m nun folgen<strong>de</strong>n einfachen Source-Co<strong>de</strong> das Debuggen<br />
mittels Einzelschritt erklären.<br />
1. Setzen <strong>de</strong>s Haltepunktes in Zeile 15<br />
13
Programm mit Haltepunkt<br />
2. Starten <strong>de</strong>s Programm mit<br />
Nach <strong>de</strong>m Start mit wird <strong>de</strong>r Haltepunkt in Zeile 15 erreicht. Die Anweisung<br />
ist noch nicht zur Ausführung gebracht wor<strong>de</strong>n. Im Fenster „Lokal“ hat die<br />
Variable intWert1 noch immer <strong>de</strong>n Wert 0.<br />
3. Fortführung durch Einzelschritt mit<br />
14
Durch <strong>de</strong>n Einzelschritt mit ist die erste Anweisung in Zeile 15 ausgeführt<br />
und die Variable intWert1 mit <strong>de</strong>m Wert 10 initialisiert wor<strong>de</strong>n. Das Fenster<br />
„Lokal“ bestätigt uns die Wertzuweisung. Der Programmzeiger ist in die<br />
nächste Zeile gewan<strong>de</strong>rt und zeigt auf die nächste auszuführen<strong>de</strong> Anweisung.<br />
4. Fortführung durch Einzelschritt<br />
Durch <strong>de</strong>n nächsten Einzelschritt mit wur<strong>de</strong> die Anweisung in Zeile 16<br />
ausgeführt und die Variable intWert2 mit <strong>de</strong>m Wert 42 initialisiert. Zwar hat<br />
sich nach <strong>de</strong>m Start <strong>de</strong>s Programms das Konsolenfenster geöffnet, doch außer<br />
einem schwarzen leeren Hintergrund ist nicht allzu viel zu sehen.<br />
15
5. Fortführung durch Einzelschritt<br />
Der letzte Einzelschritt führte die Berechnung in Zeile 17 durch und wies das<br />
Ergebnis <strong>de</strong>r <strong>de</strong>klarierten Variablen intWert3 zu. Der Programmzeiger steht<br />
mittlerweile in <strong>de</strong>r Zeile, die das Ergebnis im nächsten Schritt an die Konsole<br />
ausgibt.<br />
6. Fortführung durch Einzelschritt<br />
Durch diesen Einzelschritt wur<strong>de</strong> das Ergebnis <strong>de</strong>r letzten Berechnung an die<br />
Konsole ausgegeben. Geben Sie <strong>de</strong>m Konsolenfenster über Ihre Taskleiste <strong>de</strong>n<br />
Fokus, so dass es sichtbar wird. Die Anzeige sollte mit <strong>de</strong>m Wert 52 <strong>de</strong>r<br />
Variablen intWert3 aus <strong>de</strong>m Fenster „Lokal“ übereinstimmen.<br />
16
7. Fortführung mit Einzelschritt<br />
Durch <strong>de</strong>n Einzelschritt wur<strong>de</strong> die Kontrolle an die Konsole übergeben, die dort<br />
auf eine Bestätigung durch die Taste wartet. Der Programmzeiger hat sich<br />
vorübergehend ausgeblen<strong>de</strong>t, da eine Einzelschritt Aktion nicht möglich ist.<br />
8. Taste im Konsolenfenster drücken<br />
Erst nach<strong>de</strong>m die Konsole die Kontrolle durch <strong>de</strong>n Tastendruck zurückgegeben<br />
hat, wird <strong>de</strong>r Programmzeiger wie<strong>de</strong>r sichtbar.<br />
9. Fortführen mit Einzelschritt<br />
17
Der Programmzeiger steht jetzt vor <strong>de</strong>r schließen<strong>de</strong>n geschweiften Klammer <strong>de</strong>r<br />
Main-Metho<strong>de</strong>, was be<strong>de</strong>utet, dass <strong>de</strong>r nun folgen<strong>de</strong> Einzelschritt das<br />
Programm been<strong>de</strong>t.<br />
Debuggen ohne Haltepunkt(e)<br />
Ausführen bis Cursor<br />
Bis jetzt haben Sie zum kontrollierten Anhalten <strong>de</strong>s Programms, einen<br />
Haltepunkt an eine bestimmte Stelle Ihres Source-Co<strong>de</strong>s gesetzt. Möchten Sie<br />
Ihre Anwendung einmal ohne Haltepunkt bis zu einer gewissen Zeile ausführen,<br />
um sich Variableninhalte anzuschauen, gehen Sie folgen<strong>de</strong>rmaßen vor:<br />
1. Setzen Sie <strong>de</strong>n Cursor in die Zeile, in <strong>de</strong>r Die Ausführung unterbrochen<br />
wer<strong>de</strong>n soll<br />
2. Öffnen Sie das Kontext-Menü über die rechte Maustaste<br />
3. Wählen Sie <strong>de</strong>n Eintrag „Ausführen bis Cursor“<br />
18
Abb. 5: Ausführen bis Cursor<br />
Nach <strong>de</strong>m Start Ihrer Anwendung mit stoppt die Ausführung in Zeile 15<br />
gleichermaßen, als wenn Sie dort einen Haltepunkt eingefügt hätten. Der gelbe<br />
Programmzeiger verharrt an dieser Position jedoch mit <strong>de</strong>m Unterschied, dass<br />
kein Haltepunkt unter ihm zu erkennen ist.<br />
Haben Sie an verschie<strong>de</strong>nen Stellen Im Source-Co<strong>de</strong> Haltepunkte gesetzt und<br />
wählen diese Art <strong>de</strong>s Debuggen, so stoppt die Ausführung trotz alle<strong>de</strong>m an<br />
einem Haltepunkt, falls dieser vor <strong>de</strong>r Cursorzeile erreicht wird.<br />
Arbeiten mit <strong>de</strong>r Klasse „Debug“<br />
Die bis jetzt vorgestellte Technik <strong>de</strong>s Debuggen bezog sich auf das Ausführen<br />
<strong>de</strong>s Programms bis zu einer bestimmten Stelle im Source-Co<strong>de</strong>. Dies wur<strong>de</strong><br />
entwe<strong>de</strong>r durch das Setzen von einem o<strong>de</strong>r mehreren Haltepunkten o<strong>de</strong>r durch<br />
19
das Ausführen bis zum platzierten Cursor erreicht. Im erreichten Haltezustand<br />
war es Ihnen möglich, Daten zu inspizieren o<strong>de</strong>r sogar zu manipulieren. Um zur<br />
Laufzeit <strong>de</strong>s Programms Variableninhalte sichtbar zu machen, bedienten wir<br />
uns <strong>de</strong>r Ausgabe auf die Konsole durch die Metho<strong>de</strong> Console.WriteLine().<br />
Natürlich ist gegen diese Art <strong>de</strong>s Monitorens nichts einzuwen<strong>de</strong>n.<br />
Die Ausgabe lautet erwartungsgemäß:<br />
10<br />
42<br />
52<br />
Schwierig wird es nur, wenn Sie nicht erkennen, welches sie regulären<br />
Ausgaben sind und welche nur als Debug-Informationen fungieren. Visual<br />
Studio <strong>C#</strong> 2005 Express Edition bietet uns eine Variante an, diese Ausgaben<br />
statt an die Konsole in einem separaten Fenster auszugeben. Sie erreichen es<br />
über <strong>de</strong>n Menüpunkt Debuggen|Fenster|Ausgabe. Doch wie fin<strong>de</strong>t eine<br />
Ausgabe in dieses Fenster statt? Wir müssen uns die Funktionalität <strong>de</strong>r Klasse<br />
„Debug“ zu Nutze machen. Sie stellt eine Reihe von Metho<strong>de</strong>n zur Verfügung,<br />
<strong>de</strong>rer wir uns bedienen können. Ersetzten Sie einfach <strong>de</strong>n Klassennamen<br />
Console durch Debug. Die Ausgabemetho<strong>de</strong> lautet in bei<strong>de</strong>n Klassen<br />
WriteLine(). Än<strong>de</strong>rn wir also <strong>de</strong>n Source-Co<strong>de</strong> entsprechend ab, so dass Debug-<br />
20
Informationen nur an die dafür vorgesehene Stelle geschickt wer<strong>de</strong>n. Ersetzten<br />
Sie in <strong>de</strong>n Zeilen 17 und 20 die Klassenbezeichnung Console durch Debug.<br />
Dotty: „So einfach scheint das nicht zu sein! Ich bekomme sofort einen<br />
Fehler angezeigt.“<br />
Die Klasse Debug befin<strong>de</strong>t sich im Namespace System.Diagnostics. Sie müssen<br />
also entwe<strong>de</strong>r <strong>de</strong>n kompletten Pfad<br />
System.Diagnostics.Debug.WriteLine(…)<br />
angeben o<strong>de</strong>r die Using-Direktive<br />
using System.Diagnostics;<br />
setzten. Anschließend können Sie Debug.WriteLine(…) schreiben, weil<br />
<strong>de</strong>r Namensraum dadurch bekannt gemacht wur<strong>de</strong>. Der komplette Source-Co<strong>de</strong><br />
schaut folgen<strong>de</strong>rmaßen aus:<br />
21
Sie sehen, dass ich in Zeile 4 die Using-Direktive hinzugefügt habe. Das<br />
verkürzt die Schreibweise in <strong>de</strong>n Zeilen 14 und 17, die jetzt ohne komplette<br />
Pfadangaben auskommen. Starten Sie jetzt das Programm, so sehen Sie nur das<br />
Ergebnis <strong>de</strong>r Anweisung aus Zeile 20 im Konsolenfenster. Die Debug-<br />
Informationen sind, wie erwartet, im Ausgabe-Fenster zu fin<strong>de</strong>n.<br />
22
Abb. 6: Ausgabe Fenster<br />
Wie unschwer zu erkennen ist, beschickt <strong>de</strong>r Compiler dieses Fenster mit einer<br />
ganzen Reihe von Informationen. U.a. sehen Sie die Ausgabe <strong>de</strong>r Werte 10 bzw.<br />
42 <strong>de</strong>r Variableninhalte.<br />
Die Metho<strong>de</strong> Debug.WriteLine() kennt im Gegensatz zur Metho<strong>de</strong><br />
Console.WriteLine() keine Formatanweisungen. Die Anweisung<br />
Console.WriteLine("intWert1= {0}", intWert1);<br />
muss für die die Klasse Debug folgen<strong>de</strong>rmaßen lauten:<br />
Debug.WriteLine("intWert1= " + intWert1);<br />
Dotty: „Ich kann meine Debug-Informationen - zwar nicht auf <strong>de</strong>n ersten<br />
Blick - erkennen, doch optimal fin<strong>de</strong> ich die Ausgabe nicht.“<br />
Da gebe ich Dir Recht. Es existiert eine Metho<strong>de</strong> mit Namen I<strong>de</strong>nt(), welche<br />
alle folgen<strong>de</strong>n Ausgaben einrückt. Entschei<strong>de</strong>nd für <strong>de</strong>n Level <strong>de</strong>r Einrückung<br />
ist die Eigenschaft I<strong>de</strong>ntLevel, wobei die Eigenschaft I<strong>de</strong>ntSize die Anzahl <strong>de</strong>r<br />
einzurücken<strong>de</strong>n Zeichen angibt.<br />
23
Die Ausgabe lautet folgen<strong>de</strong>rmaßen:<br />
Abb. 7: Ausgabefenster von Debug<br />
Speichern <strong>de</strong>r Ausgabe<br />
Manche logische Fehler mögen sich als recht hartnäckig herausstellen und Sie<br />
sind auf die Debug-Informationen in chronologischer Reihenfolge angewiesen.<br />
Da bei je<strong>de</strong>m neuen Start Ihrer Anwendung <strong>de</strong>r Inhalt <strong>de</strong>s Ausgabefensters<br />
24
gelöscht wird, kann es sinnvoll sein, diesen vor je<strong>de</strong>m neuen Durchlauf zu<br />
sichern.<br />
1. Markieren Sie alle Einträge im Ausgabefenster mit <strong>de</strong>r linken Maustaste<br />
2. Klicken Sie mit <strong>de</strong>r rechten Maustaste in das Ausgabefenster und öffnen das<br />
Kontext-Menü<br />
3. Wählen Sie <strong>de</strong>n Eintrag „kopieren“<br />
4. Öffnen Sie einen Texteditor (z.B. Notepad) und fügen <strong>de</strong>n zuvor kopierten<br />
Inhalt dort ein<br />
5. Speichern Sie die Informationen in eine Datei unter einem aussagekräftigen<br />
Namen<br />
Nachfolgend eine Übersicht über die wichtigsten Metho<strong>de</strong>n und Eigenschaften<br />
<strong>de</strong>r Klasse Debug.<br />
Metho<strong>de</strong> Eigenschaft Erklärung<br />
I<strong>de</strong>nt() Einrückung <strong>de</strong>r Ausgabe um einen Level erhöhen<br />
UnI<strong>de</strong>nt() Einrückung <strong>de</strong>r Ausgabe um einen Level vermin<strong>de</strong>rn<br />
I<strong>de</strong>ntLevel Angabe <strong>de</strong>s Einrück-Levels<br />
I<strong>de</strong>ntSize Angabe <strong>de</strong>r Einrück-Zeichenanzahl pro Level<br />
Tab. 3: Metho<strong>de</strong>n und Eigenschaften <strong>de</strong>r Klasse Debug<br />
25
Fehlermeldung<br />
Source-Co<strong>de</strong> im Haltezustand bearbeiten<br />
Mir ist es schon einige Male passiert, dass sich meine Anwendung - ohne es zu<br />
wissen - noch im Haltezustand befand und ich geneigt war, <strong>de</strong>n Source-Co<strong>de</strong> zu<br />
bearbeiten. Ich wur<strong>de</strong> <strong>de</strong>shalb regelmäßig mit <strong>de</strong>m folgen<strong>de</strong>n Dialog erfreut.<br />
Been<strong>de</strong>n Sie das Debuggen durch + . Danach erhalten Sie wie<strong>de</strong>r die<br />
Möglichkeit, Ihren Source-Co<strong>de</strong> zu bearbeiten.<br />
Bedingte Kompilierung<br />
Stellen Sie sich vor, Sie befin<strong>de</strong>n sich in einer Testphase ihrer Applikation und<br />
möchten in Abhängigkeit von bestimmten Faktoren <strong>de</strong>n Programmverlauf<br />
steuern. Gera<strong>de</strong> beim Debuggen ist es sinnvoll, so viele Informationen wie<br />
möglich über <strong>de</strong>n Programmablauf zu erhalten. Um diesen Co<strong>de</strong>, <strong>de</strong>r z.B.<br />
Variableninhalte auf die Konsole ausgibt, nach <strong>de</strong>m Debuggen nicht wie<strong>de</strong>r zu<br />
löschen - man könnte ihn vielleicht bei später bei erneut auftauchen<strong>de</strong>n<br />
26
Problemen wie<strong>de</strong>r verwen<strong>de</strong>n - nutzt man die bedingte Kompilierung. Das<br />
be<strong>de</strong>utet, dass in Abhängigkeit von existieren<strong>de</strong>n Symbolen ein bestimmter<br />
Programmco<strong>de</strong> kompiliert wird o<strong>de</strong>r nicht.<br />
Dotty: „Was be<strong>de</strong>uten in diesem Zusammenhang Symbole und wie wer<strong>de</strong>n sie<br />
<strong>de</strong>finiert?“<br />
Wir benutzten zum <strong>de</strong>finieren bzw. löschen von Symbolen so genannte<br />
Direktiven.<br />
Direktive Erklärung<br />
#<strong>de</strong>fine <br />
#un<strong>de</strong>f <br />
Tab. 4: Direktiven für Symbole<br />
Definiert ein Symbol<br />
Löscht das Symbol<br />
Zu beachten ist, dass sich diese bei<strong>de</strong>n Direktiven am Beginn <strong>de</strong>s Source-Co<strong>de</strong>s<br />
befin<strong>de</strong>n müssen. Also noch vor <strong>de</strong>n eigentlichen Anweisungen. An<strong>de</strong>rnfalls<br />
gibt’s die folgen<strong>de</strong> Fehlermeldung:<br />
27
Sie sehen direkt in Zeile 1 die Direktive #<strong>de</strong>fine mit <strong>de</strong>m <strong>de</strong>finierten Symbol<br />
TEST. In <strong>de</strong>r Zeile 12 wird eine Abfrage mittels #if TEST gestartet, die<br />
überprüft, ob das Symbol TEST <strong>de</strong>finiert wur<strong>de</strong>. Falls die Antwort positiv<br />
ausfällt, wird <strong>de</strong>r Anweisungsblock zwischen #if bzw. #endif ausgeführt.<br />
Dotty: „Kann man irgendwie zu Entwicklungszeit erkennen, ob ein Symbol<br />
<strong>de</strong>finiert wur<strong>de</strong>, ohne an <strong>de</strong>n Anfang <strong>de</strong>s Source-Co<strong>de</strong>s zu springen?“<br />
Das ist möglich. Die Entwicklungsumgebung stellt die Co<strong>de</strong>zeilen, die sich<br />
innerhalb eines Anweisungsblocks befin<strong>de</strong>n, grau dar, wenn das Symbol für<br />
diesen Block nicht <strong>de</strong>finiert wur<strong>de</strong>. An<strong>de</strong>rnfalls sehen wir das übliche Syntax-<br />
Highlighting. Symbole können nicht nur innerhalb einer Datei <strong>de</strong>finiert wer<strong>de</strong>n,<br />
son<strong>de</strong>rn projektbezogen in <strong>de</strong>n Projektoptionen<br />
1. Projekt im Projektmappenexplorer markieren<br />
2. Projekteigenschaften über Kontextmenü (rechte Maustaste) aufrufen<br />
3. In <strong>de</strong>n Reiter Erstellen wechseln<br />
Sie erkennen auf <strong>de</strong>r rechten Seite ein Text-Eingabefeld, in das Sie ein o<strong>de</strong>r<br />
mehrere Symbole eingeben können. Diese sind dann für das komplette Projekt<br />
<strong>de</strong>finiert. Trennen Sie mehrere Symbole entwe<strong>de</strong>r durch Leerzeichen o<strong>de</strong>r<br />
Kommata. In diesem Fall wur<strong>de</strong>n zwei Symbole (TEST und OUT) <strong>de</strong>finiert.<br />
28
Im vorliegen Co<strong>de</strong> sehen Sie anhand <strong>de</strong>r farblichen Kodierung <strong>de</strong>r IDE, dass die<br />
Symbole TEST und OUT <strong>de</strong>finiert wur<strong>de</strong>n, jedoch nicht OUT2. Folgen<strong>de</strong><br />
Direktiven sind zur Steuerung <strong>de</strong>r Kompilierung verfügbar:<br />
Direktive Erklärung<br />
#if<br />
#else<br />
#elif<br />
#endif<br />
Tab. 5: Direktiven für Symbole<br />
Einleitung <strong>de</strong>s Anweisungsblocks<br />
Else-Anweisung<br />
Else-If Anweisung<br />
Beendung <strong>de</strong>s Anweisungsblocks<br />
29
Attribut Conditional<br />
Sie können <strong>de</strong>n Programmablauf zusätzlich über ein Attribut steuern, welches<br />
das Vorhan<strong>de</strong>nsein eines Symbols auswertet, das mit einer Direktive gesetzt<br />
o<strong>de</strong>r gelöscht wur<strong>de</strong>. Das Attribut nennt sich Conditional. Das zu<br />
überprüfen<strong>de</strong> Symbol wird als Zeichenkette innerhalb von doppelten<br />
Hochkommata und <strong>de</strong>n run<strong>de</strong>n Klammern hinter <strong>de</strong>m Attribut aufgeführt.<br />
Schauen Sie sich das folgen<strong>de</strong> Beispiel an:<br />
30
Das Attribut Conditional platzieren Sie einfach vor je<strong>de</strong> Metho<strong>de</strong>, die über<br />
ein Symbol gesteuert wer<strong>de</strong>n soll.<br />
1. Definieren <strong>de</strong>s Symbols TEST<br />
2. Namespace System.Diagnostics über using bekannt machen<br />
3. Platzieren <strong>de</strong>s Attributes vor die zu kontrollieren<strong>de</strong>n Metho<strong>de</strong>n<br />
In Zeile 12 bzw. 13 wer<strong>de</strong>n die bei<strong>de</strong>n Metho<strong>de</strong>n aufgerufen, doch vor <strong>de</strong>r<br />
eigentlichen Ausführung wertet das Attribut das nachfolgend aufgeführte<br />
Symbol aus. Existiert es, wird die Metho<strong>de</strong> ausgeführt, an<strong>de</strong>rnfalls ignoriert.<br />
Compilermeldungen<br />
Deaktivieren / Aktivieren<br />
Ihnen ist es sicherlich schon aufgefallen, dass Sie einen Warnhinweis vom<br />
Compiler erhalten, wenn eine Variable zwar <strong>de</strong>klariert, jedoch an keiner Stelle<br />
Ihres Programms genutzt wird. Falls Sie diese Warnungen stören, weil Sie<br />
vielleicht doch diese Variablen im späteren Verlauf Ihres Projektes nutzen<br />
möchten, gibt es eine Möglichkeit Compilermeldungen zu konfigurieren. Der<br />
folgen<strong>de</strong> kurze Co<strong>de</strong> <strong>de</strong>klariert und initialisiert zwar die Variable intVariable1,<br />
doch sie es wird nie darauf zugegriffen.<br />
Die grünen Schlangenlinien weisen auf einen Warnhinweis hin, <strong>de</strong>r da lautet:<br />
31
Je<strong>de</strong> Warnmeldung besitzt intern einen Co<strong>de</strong> bzw. eine Nummer. Lei<strong>de</strong>r wird<br />
<strong>de</strong>r an dieser Stelle nicht angezeigt. Wie können wir ihn also ermitteln? Gehen<br />
Sie dabei folgen<strong>de</strong> Schritte durch:<br />
1. Platzieren Sie <strong>de</strong>n Cursor über die Variable, die mit Schlangenlinien<br />
unterlegt ist<br />
2. Drücken Sie die Funktionstaste F1<br />
Es dauert eine Weile, bis sich die Visual <strong>C#</strong>-Referenz öffnet.<br />
Der entschei<strong>de</strong>n<strong>de</strong> Hinweis ist die Zeile, in <strong>de</strong>r die Compilerwarnung steht. Der<br />
für uns wichtige Co<strong>de</strong> lautet 219. Jetzt müssen wir <strong>de</strong>m Compiler mitteilen,<br />
dass wir nicht mehr an Warnungen interessiert sind, die in diese Kategorie<br />
fallen. dazu existiert eine Direktive. Sie lautet:<br />
#pragma warning<br />
Um die Warnung zu <strong>de</strong>aktivieren, fügen Sie die in Zeile 3 stehen<strong>de</strong> Direktive an<br />
<strong>de</strong>n Anfang Ihres Co<strong>de</strong>s ein:<br />
32
Die Direktive<br />
#pragma warning restore 219<br />
veranlasst <strong>de</strong>n Compiler wie<strong>de</strong>r Meldungen zu schicken und die Zeile<br />
#pragma warning restore<br />
stellt <strong>de</strong>n Urzustand wie<strong>de</strong>r her, so dass alle Meldungen <strong>de</strong>n Entwickler<br />
erfreuen. Be<strong>de</strong>nken Sie aber auf je<strong>de</strong>n Fall, dass <strong>de</strong>r Compiler nicht ohne Grund<br />
diese Meldungen verschickt. Es könnte u.U. wichtig sein.<br />
Sie können mehrere Co<strong>de</strong>s durch Kommata getrennt angeben, um<br />
Warnungen zu <strong>de</strong>aktivieren bzw. aktivieren.<br />
33
Eigene Meldungen erstellen<br />
Es ist unter gewissen Umstän<strong>de</strong>n sogar sinnvoll, eigene Warnungen zu<br />
erstellen, um Sie bei passen<strong>de</strong>r Gelegenheit auszulösen.<br />
Dotty: „Wann sollte das <strong>de</strong>nn nötig sein? Stellt <strong>de</strong>r Compiler etwas fest, das<br />
für <strong>de</strong>n Programmierer wichtig ist, bekommt er doch sicherlich einen<br />
Hinweis.“<br />
Das ist sicherlich korrekt. Doch mal angenommen, wir haben die schon<br />
angesprochene bedinge Kompilierung aktiviert. Da kann es u.U. nützlich sein,<br />
eine entsprechen<strong>de</strong> Meldung zu generieren, damit <strong>de</strong>r Programmierer über<br />
dieses geän<strong>de</strong>rte Programmverhalten informiert wird.<br />
34
Die Meldung im Fehlerlisten-Fenster lautet entsprechend:<br />
35