## 2.2 Grundlagen der C#-Syntax ### 2.2.1 Kennzeichnen, dass eine Anweisung abgeschlossen ist C#-Programme setzen sich, wie auch in anderen Sprachen entwickelte Programme, aus vielen Anweisungen zusammen, die der Reihe nach ausgeführt werden. Anweisungen legen fest, was das Programm zu tun hat und auf welche Art und Weise es das tut. Sie haben im vorherigen Abschnitt bereits Ihr erstes Programm geschrieben, das aus zwei Anweisungen bestand:
    Console.WriteLine("C# macht Spaß.");
    Console.ReadLine();
Jede Anweisung verlangt nach einer Kennzeichnung, die das Ende der Anweisung bekannt gibt. Dazu wird in C# das Semikolon eingesetzt. Wenn Sie das Semikolon vergessen, erhalten Sie einen Kompilierfehler. Im vorhergehenden Abschnitt hatten wir das sogar provoziert. Auch wenn es sinnlos ist, so dürfen Sie durchaus mehrere Semikolons hintereinanderschreiben, ohne dass explizit eine Anweisung dazwischen stehen muss:
    ;;;;
Weil durch ein Semikolon eine Anweisung eindeutig abgeschlossen wird, dürfen auch mehrere Anweisungen in eine Zeile geschrieben werden. Im Umkehrschluss kann eine Anweisung auch problemlos auf mehrere Zeilen verteilt werden, ohne dass sich der Compiler daran stört. Bei der Gestaltung des Programmcodes lässt C# Ihnen sehr viele Freiheiten. Leerzeichen, Tabulatoren und Zeilenumbrüche können nach Belieben eingestreut werden, ohne dass sich das auf die Kompilierung des Quellcodes oder die Ausführung des Programms auswirkt. Daher dürfte der Code unseres Beispiels auch wie folgt aussehen:
    Console.
       WriteLine("C# macht Spaß.")    ;
      Console.
          ReadLine   (
    )
          ;
Dass eine Streuung wie die gezeigte die gute Lesbarkeit des Codes enorm beeinträchtigt, steht außer Frage. Aber C# führt diesen Code dennoch genauso aus wie zuvor. Andererseits kann man insbesondere mit den Tabulatoren über Einrückungen zu einer guten Lesbarkeit des Programmcodes beitragen. Vergleichen Sie dazu wieder das Beispiel von oben. Anweisungen, die innerhalb eines Anweisungsblocks in geschweiften Klammern stehen, werden üblicherweise rechts eingerückt. Wenn Sie sich an den Beispielen in diesem Buch orientieren, werden Sie sehr schnell ein Gefühl dafür bekommen, wie Sie mit Einrückungen nicht nur optisch ansprechenden, sondern auch leichter lesbaren Code schreiben. Feste Regeln gibt es dazu allerdings nicht, es sind stillschweigende Konventionen. ### 2.2.2 Anweisungs- und Gliederungsblöcke C#-Programmcode ist blockorientiert, d. h., dass C#-Anweisungen grundsätzlich immer innerhalb eines Paars geschweifter Klammern geschrieben werden. Jeder Block kann eine beliebige Anzahl von Anweisungen enthalten – oder auch keine. Somit hat ein Anweisungsblock allgemein die folgende Form:
    {
       Anweisung 1;
       Anweisung 2;
       ...
    }
Anweisungsblöcke lassen sich beliebig ineinander verschachteln. Dabei beschreibt jeder Anweisungsblock eine ihm eigene Ebene, zum Beispiel:
    {
       Anweisung 1;
       {
          Anweisung 2;
          Anweisung 3;
       }
       Anweisung 4;
    }
Beachten Sie, wie Einzüge hier dazu benutzt werden, optisch die Zugehörigkeit einer oder mehrerer Anweisungen zu einem bestimmten Block aufzuzeigen. Die Anweisungen 2 und 3 sind zu einem Block zusammengefasst, der sich innerhalb eines äußeren Blocks befindet. Zum äußeren Anweisungsblock gehören Anweisung 1 und Anweisung 4 sowie natürlich auch der komplette innere Anweisungsblock. Außer zur Blockbildung von Anweisungen werden die geschweiften Klammern dazu benutzt, Definitionsbereiche zu bilden. Beispielsweise lassen sich mehrere Klassendefinitionen einem bestimmten Namespace zuordnen. Um dieses Thema zu erörtern, ist es allerdings noch zu früh. ### 2.2.3 Kommentare Sie sollten nicht mit Kommentaren geizen. Kommentare helfen, den Programmcode der Anwendung besser zu verstehen. Sie tun nicht nur den Entwicklern damit einen Gefallen, die sich mit Ihrem Code auseinandersetzen müssen, sondern auch sich selbst. Wenn Sie bereits Programmiererfahrung haben, werden Sie wissen, wie schwierig es ist, nach dem dreiwöchigen Mallorca-Urlaub wieder den eigenen Code zu verstehen. Was beschreibt diese Variable, welche Funktionalität steckt hinter jener Methode? Ersparen Sie sich und anderen die unnötige und zeitraubende Suche nach den Antworten. C# bietet zwei Möglichkeiten, um Kommentare, die vom Compiler während des Kompiliervorgangs ignoriert werden, in den Quellcode einzustreuen. Die am häufigsten benutzte Variante ist die Einleitung eines Kommentars mit zwei Schrägstrichen //:
    // dies ist ein Kommentar
Ein //-Kommentar gilt für den Rest der gesamten Codezeile, kann jedes beliebige Zeichen enthalten und darf auch nach einer abgeschlossenen Anweisung stehen.
    Console.WriteLine("..."); //Konsolenausgabe
Sollen viele zusammenhängende Zeilen zu einem längeren Kommentar zusammengefasst werden, bietet sich die zweite Alternative an, bei der ein Kommentar mit /* eingeleitet und mit */ abgeschlossen wird. Alle Zeichen, die sich dazwischen befinden, sind Bestandteil des Kommentars.
    /* Console.WriteLine("...");
    Console.ReadLine();*/
Tatsächlich kann man sogar mitten in einer Anweisung diesen Kommentar schreiben, ohne dass der C#-Compiler das als Fehler ansieht:
    Console.WriteLine /* Kommentar */("...");
Hinweis
Eine weitere Variante eines Kommentars in C# ist durch drei aufeinanderfolgende Schrägstriche /// gekennzeichnet. Codezeilen, die so auskommentiert sind, werden zwar ebenfalls vom C#-Compiler ignoriert, ihnen kommt aber eine weiterreichende Bedeutung zu: Sie dienen zum Erstellen einer XML-basierten Dokumentation.
Die Entwicklungsumgebung des Visual Studio 2010 bietet eine recht interessante und einfache Alternative, um insbesondere größere Blöcke auf einmal auszukommentieren. Sie müssen dazu nur sicherstellen, dass in der Entwicklungsumgebung die Symbolleiste Text-Editor angezeigt wird. Dazu brauchen Sie nur mit der rechten Maustaste das Kontextmenü einer der aktuellen Symbolleisten zu öffnen. Im Kontextmenü finden Sie alle Symbolleisten der Entwicklungsumgebung aufgelistet. Da die Anzahl als nicht gering bezeichnet werden kann, lassen sich die einzelnen Symbolleisten nach Bedarf ein- oder ausblenden. Die Symbolleiste Text-Editor enthält zwei Schaltflächen, um markierte Codeblöcke auszukommentieren oder eine Kommentierung wieder aufzuheben (siehe Abbildung 2.3). Hier klicken, um das Bild zu vergrößern Abbildung 2.3 Kommentare mithilfe der Symbolleiste
Anmerkung
In diesem Buch werden alle Kommentare grau hinterlegt, um auf einen Blick deutlich zwischen Code und Kommentar unterscheiden zu können. Außerdem bezieht sich jeder Kommentar auf die folgende Codezeile.
In der Entwicklungsumgebung erscheinen Kommentare in einer anderen Schriftfarbe als der Programmcode selbst. Sie können die Farbgebung ganz individuell festlegen, wenn Sie den Dialog Optionen öffnen und im Knoten Umgebung den Punkt Schriftarten und Farben auswählen. Rechts neben dem Listenfeld bieten sich anschließend mehrere Optionen, um die Darstellung des Programmcodes im Codefenster zu beeinflussen. ### 2.2.4 Groß- und Kleinschreibung C# gehört zu der Gruppe von Programmiersprachen, die zwischen Groß- und Kleinschreibung unterscheiden. Falls Sie die Anweisung zur Konsolenausgabe mit
    Console.Writeline("...");
codieren, werden Sie bei der Kompilierung mit einer Fehlermeldung konfrontiert. Korrekt müsste es lauten:
    Console.WriteLine("...");
Es ist Ansichtssache, ob man diese kleinkarierte Interpretation von C# für positiv oder negativ hält, denn beispielsweise macht VB.NET hier keinen Unterschied. Positiv ist jedenfalls zu bemerken, dass zwei gleichlautende Bezeichner, die sich nur durch Groß- und Kleinschreibung unterscheiden, in C# auch für zwei unterschiedliche Programmelemente stehen. Manchmal erleichtert C# die Festlegung eines Bezeichners für eine Variable und kann außerdem zur eindeutigen Zuordnung zweier miteinander in einer logischen Beziehung stehenden Variablen dienen. ### 2.2.5 Struktur einer Konsolenanwendung Sehen wir uns noch einmal den Code an, den uns die Entwicklungsumgebung nach dem Öffnen eines neuen Projekts vom Typ Konsolenanwendung anbietet:
    using System;
    using System.Collections.Generic;
    using System.Text;
    namespace ConsoleApplication1
    {
      class Program
      {
        static void Main(string[] args)
        {
        }
      }
    }
Wir erkennen nun eindeutig mehrere ineinandergeschachtelte Blockstrukturen. Der äußere Block definiert einen Namespace mit dem Namen ConsoleApplication1. Namespaces dienen dazu, die Typen der .NET-Klassenbibliothek funktionell orientiert zu organisieren und innerhalb eines Namespace die namentliche Eindeutigkeit zu gewährleisten.
Anmerkung
Der Bezeichner eines Namespace, in unserem Beispiel ConsoleApplication1, wird beim Start eines neuen Projekts automatisch vergeben und entspricht dem Projektnamen. Sie können diese Vorgabe ändern, solange der frei gewählte Name seinerseits innerhalb seines Definitionsbereichs eindeutig ist.
Im Namespace eingebettet ist eine Klassendefinition, die einen eigenen Anweisungsblock beschreibt:
    namespace ConsoleApplication1
    {
      class Program
      {
      }
    }
C# ist eine 100%ig objektorientierte Sprache. Das bedeutet, dass grundsätzlich immer eine Klassendefinition vorliegen muss, um mit einem Objekt arbeiten zu können. Eine Klasse beschreibt einen Typ, und in unserem Fall heißt dieser Typ Program. Der Bezeichner Program ist nur als Vorschlag der Entwicklungsumgebung anzusehen und darf im Rahmen der Eindeutigkeit innerhalb des aktuellen Namespace (hier also ConsoleApplication1) nahezu frei vergeben werden. Über die Einschränkungen werden wir uns später noch Gedanken machen müssen. Wie Sie sehen, kommen wir schon an dieser Stelle zum ersten Mal mit Klassen in Kontakt, die uns bei allen auf dem .NET Framework basierenden Anwendungen begleiten. Was eine Klasse selbst darstellt und wie man sie einsetzt, wird einen wesentlichen Teil dieses Buches ausmachen. Wir wollen es hier aber zunächst bei dieser kurzen Erwähnung belassen, denn in diesem Kapitel werden Sie die grundlegende Syntax von C# lernen, ohne die Gesichtspunkte des objektorientierten Paradigmas berücksichtigen zu müssen. Interessanter ist für uns momentan die dritte Blockebene, die innerhalb der Klasse Program vordefiniert ist, nämlich die durch Main beschriebene:
    static void Main(string[] args)
    {
    }
Bei Main handelt es sich um eine Prozedur, die für uns von herausragender Bedeutung ist: Wenn wir die Laufzeitumgebung einer Anwendung starten, werden zuerst Main und die darin enthaltenen Anweisungen ausgeführt. Sie dürfen den Namen dieser Prozedur nicht ändern und müssen natürlich auch die Großschreibweise berücksichtigen, denn beim Start der Laufzeitumgebung wird immer nach Main gesucht und nicht nach main oder nach start. Weiter oben wurde gesagt, dass Anweisungen immer innerhalb eines Blocks aus geschweiften Klammern codiert werden. Wir können diese Aussage nun präzisieren: Anweisungen werden grundsätzlich immer innerhalb des Anweisungsblocks einer Prozedur implementiert. Wir haben das schon bei unserem ersten Beispiel gesehen:
    static void Main(string[] args)
    {
       Console.WriteLine("C# macht Spaß.");
       Console.ReadLine();
    }
An dieser Stelle wollen wir uns schon mit einem weiteren Begriff anfreunden, der Ihnen in diesem Kapitel immer wieder begegnen wird, dessen Bedeutung allerdings erst in Kapitel 3 exakt beschrieben wird: Es handelt sich hierbei um den Begriff der Methode. In Programmiersprachen, die nicht auf Klassen und Objekten basieren, wird eine Prozedur als eine zusammengehörige Anweisungsfolge definiert, die zur Laufzeit der Reihe nach abgearbeitet wird – nicht anders verhält sich Main. Tatsächlich ist die Verwandtschaft zwischen einer Prozedur und einer Methode auch nicht von der Hand zu weisen. Weil Main jedoch innerhalb einer Klasse definiert ist, in unserem Fall in Program, dürfen wir statt von der Main-Prozedur auch von der Main-Methode sprechen. Sehen wir uns nun noch kurz die Definition der Main-Methode an. Die beiden dem Bezeichner vorausgehenden Schlüsselwörter static und void sind zwingend notwendig. Sollten Sie bereits mit C++ oder Java Anwendungen entwickelt haben, werden Sie die Bedeutung dieser beiden Modifizierer kennen: Mit static werden Methoden bezeichnet, die beim Aufruf kein konkretes Objekt voraussetzen, und void beschreibt eine Methode ohne Rückgabewert. Im Moment soll diese Information genügen, denn eine genauere Kenntnis hätte derzeit keine Auswirkungen auf die ersten Schritte in die Welt der C#-Programme. Sie starten ein Konsolenprogramm, indem Sie den Namen der Anwendungsdatei mit der Dateierweiterung .EXE an der Konsole eingeben (die anderen sich bietenden Möglichkeiten über den Explorer bzw. über Start • Ausführen seien hier nur am Rande erwähnt). Manchmal ist es notwendig, dem Programm beim Start Anfangswerte mitzuteilen, die vom laufenden Programm zur Ausführung und Weiterverarbeitung benötigt werden. Angenommen, Sie wollen einer Konsolenanwendung mit dem Dateinamen MyApplication.exe die drei Zahlen 10, 14 und 17 übergeben, dann sähe der Aufruf an der Eingabeaufforderung wie folgt aus:
    MyApplication.exe 10 14 17
Diese drei Zahlen werden von der Parameterliste, die hinter dem Bezeichner Main in runden Klammern angegeben ist, in Empfang genommen:
    Main(string[] args) ...
Wie die übergebenen Daten mittels Programmcode verarbeitet werden, erkläre ich später. Die Angabe der Parameterliste ist optional. Benötigt ein Programm bei seinem Aufruf keine Daten, kann die Parameterliste leer bleiben. Die Angabe der runden Klammern ist aber unbedingt erforderlich:
    static void Main() ...