Rheinwerk Computing <openbook>
Rheinwerk Computing - Programming the Net


C# von Eric Gunnerson
Die neue Sprache für Microsofts .NET-Plattform
C# - Zum Katalog
gp Kapitel 27 Weitere Sprachdetails
  gp 27.1 Die Main-Funktion
  gp 27.2 Vorverarbeitung
  gp 27.3 Lexikalische Details

Kapitel 27 Weitere Sprachdetails

In diesem Kapitel werden verschiedene Sprachdetails besprochen, u. a. die Verwendung der Main()-Funktion, die Funktionsweise des Präprozessors und das Schreiben literaler Werte.


Rheinwerk Computing

27.1 Die Main-Funktion  downtop

Die einfachste Version der Main()-Funktion kennen Sie bereits aus den bisherigen Beispielen:

using System;
class Test
{
    public static void Main()
    {
        Console.WriteLine("Hello, Universe!");
    }
}

Rheinwerk Computing

27.1.1 Zurückgeben eines int-Status  downtop

Es ist häufig sinnvoll, über die Main()-Funktion einen Statuswert zurückzugeben. Dies wird erreicht, indem der Rückgabetyp von Main() als integer deklariert wird:

using System;
class Test
{
    public static int Main()
    {
        Console.WriteLine("Hello, Universe!");
        return(0);
    }
}

Rheinwerk Computing

27.1.2 Befehlszeilenparameter  downtop

Auf die Befehlszeilenparameter einer Anwendung kann durch Deklarieren der Main()-Funktion mit einem string-Array als Parameter zugegriffen werden. Die Parameter können anschließend durch Indizierung des Arrays verarbeitet werden.

using System;
class Test
{
    public static void Main(string[] args)
    {
        foreach (string arg in args)
        Console.WriteLine("Arg: {0}", arg);
    }
}

Rheinwerk Computing

27.1.3 Mehrere Main-Funktionen  downtop

Es ist zu Testzwecken häufig sinnvoll, eine statische Funktion in eine Klasse aufzunehmen, mit der die Klasse auf ihre ordnungsgemäße Funktionsweise getestet wird. In C# kann diese statische Testfunktion als Main()-Funktion geschrieben werden, was eine automatisierte Prüfung vereinfacht.

Wird während der Kompilierung eine einzelne Main()-Funktion ermittelt, verwendet der C#-Compiler diese. Sind mehrere Main()-Funktionen vorhanden, kann die Klasse mit der gewünschten Main()-Funktion über die Befehlszeilenoption /main:<Klassenname> angegeben werden.

// Fehler
using System;
class Complex
{
    public static int Main()
    {
        // Hier Code testen
        Console.WriteLine("Console: Passed");
        return(0);
    }
}
class Test
{
    public static void Main(string[] args)
    {
        foreach (string arg in args)
        Console.WriteLine(arg);
    }
}

Das Kompilieren dieser Datei mit /main:Complex führt dazu, dass die Testversion von Main() verwendet wird; beim Kompilieren mit /main:Test wird die richtige Version von Main() eingesetzt. Das Kompilieren ohne Befehlszeilenoption führt zu einem Fehler.


Rheinwerk Computing

27.2 Vorverarbeitung  downtop

Beim C#-Präprozessor müssen Sie vor allem beachten, dass dieser nicht vorhanden ist. Die Funktionen des C/C++-Prozessors stehen entweder gar nicht oder nur eingeschränkt zur Verfügung. Zu den nicht verfügbaren Funktionen gehören include-Dateien und die Fähigkeit, Textersetzungen mit #define durchzuführen. Die Direktive #ifdef und verknüpfte Direktiven sind vorhanden und werden zur Steuerung der Codekompilierung eingesetzt.

Durch die Abwesenheit der Makroversion von #define werden die Programme dem Programmierer verständlicher. Ein Name, der nicht bekannt ist, muss aus einem der Namespaces kommen, d. h., es müssen keine include-Dateien durchsucht werden.

Einer der wichtigsten Gründe für diese Änderung liegt darin, dass durch den Wegfall von Vorverarbeitung und #include eine einfachere Kompilierungsstruktur erzielt wird, wodurch die Kompilierungsgeschwindigkeit erheblich gesteigert werden kann. Zusätzlich ist es nicht länger nötig, eine separate Headerdatei zu schreiben und diese mit der Implementierungsdatei zu synchronisieren.

Bei der Kompilierung von C#-Dateien spielt die Kompilierungsreihenfolge der einzelnen Dateien keine Rolle, genauso können sich auch alle Dateien in einer großen Datei befinden. Es ist nicht erforderlich, Deklarationen weiterzuleiten oder sich über die Reihenfolge von #include-Dateien Gedanken zu machen.


Rheinwerk Computing

27.2.1 Vorverarbeitungsdirektiven  downtop

Es werden folgende Vorverarbeitungsdirektiven unterstützt:

Direktive Beschreibung
#define-Bezeichner Definiert einen Bezeichner. Beachten Sie, dass kein Wert gesetzt werden kann; dieser kann nur definiert werden. Bezeichner können auch über die Befehlszeile definiert werden.
#undef-Bezeichner Hebt die Definition für einen Bezeichner auf.
#if-Ausdruck Code in diesem Abschnitt wird kompiliert, wenn der Ausdruck wahr (true) ist.
#elif-Ausdruck Else-If-Struktur. Wenn die vorstehende Direktive nicht verwendet wurde und der Ausdruck wahr ist, wird der Code in diesem Abschnitt kompiliert.
#else Wenn die vorstehende Direktive nicht verwendet wurde, wird der Code in diesem Abschnitt kompiliert.
#endif Markiert das Ende eines Abschnitts.

Hier ein Verwendungsbeispiel:

#define DEBUGLOG
using System;
class Test
{
    public static void Main()
    {
        #if DEBUGLOG
        Console.WriteLine("In Main – Debug Enabled");
        #else
        Console.WriteLine("In Main – No Debug");
        #endif
    }
}

#define und #undef müssen in einer Datei einem Abschnitt mit »richtigem Code« vorangestellt sein, sonst tritt ein Fehler auf. Das vorgenannte Beispiel kann folgendermaßen umgeschrieben werden:

// Fehler
using System;
class Test
{
    #define DEBUGLOG
    public static void Main()
    {
        #if DEBUGLOG
        Console.WriteLine("In Main – Debug Enabled");
        #else
        Console.WriteLine("In Main – No Debug");
        #endif
    }
}

Präprozessorausdrücke

In Präprozessorausdrücken können folgende Operatoren eingesetzt werden:

Operator Beschreibung
! ex Ausdruck ist wahr, wenn ex falsch ist.
ex == value Ausdruck ist wahr, wenn ex gleich value.
ex !== value Ausdruck ist wahr, wenn ex ungleich value.
ex1 && ex2 Ausdruck ist wahr, wenn sowohl ex1 als auch ex2 wahr sind.
ex1 || ex2 Ausdruck ist wahr, wenn entweder ex1 oder ex2 wahr ist.

Mit Hilfe von Klammern können Ausdrücke gruppiert werden:

#if !(DEBUGLOG && (TESTLOG || USERLOG))

Wenn TESTLOG oder USERLOG definiert ist und DEBUGLOG definiert ist, ist der Ausdruck innerhalb der Klammern wahr und wird dann durch ! negiert.


Rheinwerk Computing

27.2.2 Andere Präprozessorfunktionen  downtop

Neben den Funktionen #if und #define können einige weitere Präprozessorfunktionen verwendet werden.

#warning und #error

#warning und #error ermöglichen die Ausgabe von Warnungen oder Fehlern während der Kompilierung. Sämtlicher Text, der auf #warning oder #error folgt, wird ausgegeben, wenn der Compiler die betreffende Zeile erreicht.

Für einen Codeabschnitt wäre Folgendes denkbar:

#warning Check algorithm with John

Bei Kompilierung dieser Zeile würde die Zeichenfolge »Check algorithm with John« ausgegeben.

#line

Mit #line kann der Programmierer den Namen der Quelldatei und die Zeilennummer angeben, die bei der Ermittlung eines Fehlers durch den Compiler ausgegeben werden sollen. Diese Methode wird typischerweise bei maschinengeneriertem Quellcode eingesetzt, damit die ausgegebenen Zeilen mit einem anderen Benennungs- oder Nummernsystem synchronisiert werden können.


Rheinwerk Computing

27.3 Lexikalische Details  downtop

Die lexikalischen Details der Sprache befassen sich mit Dingen, die auf Einzelzeichenebene von Bedeutung sind. Hierzu zählen beispielsweise das Schreiben numerischer Konstanten, Bezeichner und andere Lowleveleinheiten der Sprache.


Rheinwerk Computing

27.3.1 Bezeichner  downtop

Ein Bezeichner ist ein Name, der für ein Programmelement verwendet wird, z. B. eine Variable oder eine Funktion.

Bezeichner müssen mit einem Buchstaben oder einem Unterstrich beginnen, der verbleibende Teil des Bezeichners kann auch Zahlen enthalten. Unicode-Zeichen können über \udddd angegeben werden, wobei dddd den Hexadezimalwert des Unicode-Zeichens angibt.

Bei der Verwendung von Code, der in einer anderen Sprache geschrieben wurde, kann es sich bei einigen Namen um C#-Schlüsselwörter handeln. Zum Schreiben solcher Namen kann vor dem Namen ein at-Zeichen (@) eingefügt werden. Hierdurch wird C# darüber informiert, dass es sich nicht um ein Schlüsselwort, sondern um einen Bezeichner handelt.

Ebenso kann das @-Zeichen zur Verwendung von Schlüsselwörtern als Bezeichner eingesetzt werden:

class Test
{
    public void @checked()
    {
    }
}

Diese Klasse deklariert eine Mitgliederfunktion namens checked.

Das Verwenden dieser Funktion zur Gleichstellung von Bezeichnern mit den integrierten Bezeichnern wird nicht empfohlen, da es Verwirrung stiften kann.

Schlüsselwörter

Schlüsselwörter sind reservierte Wörter, die nicht als Bezeichner eingesetzt werden können. In C# gibt es folgende Schlüsselwörter:

abstract ba4se bool break; byte
case catch char checked class
const continue; decimal default: delegate
do double else enum event
explicit extern false finally fixed
float for foreach goto if
implicit in int interface internal
is lock long namespace new
null object operator out override
params private protected public readonly
ref return sbyte sealed short
sizeof static string struct switch
this throw true try typeof
uint ulong unchecked unsafe ushort
using virtual void while  


Rheinwerk Computing

27.3.2 Literale  downtop

Literale stellen die Möglichkeit dar, Werte für Variablen zu schreiben.

Boolesche Literale

Es gibt zwei boolesche Literale: true und false.

Ganzzahlige Literale

Ganzzahlige Literale werden einfach durch das Schreiben der numerischen Werte geschrieben. Ganzzahlige Literale, die klein genug sind, um in den int-Datentyp zu passen, werden als integer-Werte behandelt, wenn sie zu groß sind, werden sie als kleinste Typen von uint, long oder ulong erstellt.

Hier einige Beispiele für ganzzahlige Literale:

123
-15

Ganzzahlige Literale können auch im Hexadezimalformat dargestellt werden, indem vor der Konstante ein »0x« eingefügt wird.

0xFFFF
0x12AB

Reale Literale

Reale Literale werden für die Typen float, double und decimal verwendet. Float-Literale weisen ein nachgestelltes »f« oder »F« auf, double-Literale ein »d« oder »D«, an decimal-Literale wird ein »m« oder »M« angehängt. Reale Literale ohne Typenzeichen werden als double-Literale interpretiert.

Die exponentielle Notierung wird durch das Anhängen eines »e« und des Exponenten an den literalen Wert ausgedrückt.

Beispiele:

1.345                    // double-Konstante
-8.99e12F                // float-Konstante
15.66m                   // decimal-Konstante

Zeichenliterale

Ein Zeichenliteral ist ein einzelnes, von einfachen Anführungszeichen umschlossenes Zeichen, beispielsweise ’x’. Es werden folgende Escapesequenzen unterstützt:

Escapesequenz Beschreibung
\’xe »_ Einfaches Anführungszeichen
\\" Doppeltes Anführungszeichen
\\ Umgekehrter Schrägstrich (Backslash)
\0 Null
\a Alert (Warnung)
\b Rückschritt
\f Vorschub
\n Neue Zeile
\r Wagenrücklaufzeichen
\t Tabulator
\v Vertikaler Tabulator
\xdddd Zeichen dddd, wobei d für eine Hexadezimalstelle steht

Zeichenfolgenliterale

Zeichenfolgenliterale werden als eine in doppelte Anführungszeichen eingeschlossene Zeichensequenz dargestellt, beispielsweise »Hello«. Innerhalb von Zeichenfolgen werden alle Zeichenescapesequenzen unterstützt.

Zeichenfolgen dürfen nicht mehrere Zeilen umfassen, der gleiche Effekt kann jedoch durch eine Verkettung erzielt werden\:

string s = \"What is your favorite color?\" +
             \"Blue. No, Red. \";

Bei der Codekompilierung wird eine einzige Zeichenfolgenkonstante erstellt, die aus zwei verketteten Zeichenfolgen besteht.

Wörtliche Zeichenfolgen

Wörtliche Zeichenfolgen ermöglichen das einfachere Angeben einiger Zeichenfolgen.

Wenn eine Zeichenfolge einen umgekehrten Schrägstrich enthält, beispielsweise einen Dateinamen, kann mit Hilfe einer wörtlichen Zeichenfolge die Unterstützung für Escapesequenzen deaktiviert werden. Statt der Zeile\:

string s = \"c\:\\Program Files\\Microsoft Office\\Office\";

kann folgende Zeile verwendet werden\:

string s = @\"c\:\Program Files\Microsoft Office\Office\";

Die wörtliche Zeichenfolgensyntax ist demnach nützlich, wenn der Code durch ein Programm generiert wird und die Inhalte der Zeichenfolgen nicht eingeschränkt werden können. Innerhalb dieser Zeichenfolgen können alle Zeichen dargestellt werden, es müssen jedoch einige der doppelten Anführungszeichen mehrfach verwendet werden\:

string s = @\"She said, \"\"Hello\"\"\";

Darüber hinaus können in der wörtlichen Zeichenfolgensyntax geschriebene Zeichenfolgen mehrere Zeilen umfassen, vorhandene Leerzeichen (Leerzeichen, Tabulatoren, neue Zeilen) werden hierbei beibehalten.

using System;
class Test
{
    public static void Main()
    {
        string s = @\"
        C\: Hello, Miss?
        O\: What do you mean, 'Miss'?
        C\: I'm Sorry, I have a cold. I wish to make a complaint.\";
        Console.WriteLine(s);
    }
}

Rheinwerk Computing

27.3.3 Kommentare  toptop

In C# werden einzeilige Kommentare durch einen doppelten Schrägstrich gekennzeichnet, der Anfang und das Ende eines mehrzeiligen Kommentars wird mit /* und */ markiert.

// Dies ist ein einzeiliger Kommentar
/*
 * Hier mehrzeiligen Kommentar einfügen
 */

C# unterstützt darüber hinaus eine besondere Art Kommentar, um die Dokumentation mit dem Code zu verknüpfen. Diese Kommentare werden in Kapitel 31, C# im Detail, im Abschnitt zur XML-Dokumentation beschrieben.






1    Als ich zum ersten Mal eine Kopie des Compilers auf meinem System installierte, gab ich ein einfaches Beispiel ein und kompilierte dieses. Die Kompilierung wurde sehr schnell ausgeführt – so schnell, dass ich einen Fehler vermutete und einen Entwickler um Hilfe bat. Der Compiler ist sehr viel schneller als ein C++-Compiler (je sein könnte).

2    Abgesehen davon, dass die Ausgabedatei automatisch mit dem Namen der zuerst kompilierten Datei versehen wird.

3    Es ist tatsächlich etwas komplizierter als hier dargestellt, da C# über Unicode-Unterstützung verfügt. Kurz gesagt, bei den Buchstaben kann es sich um ein beliebiges Unicode-Zeichen handeln, und alle Zeichen außer dem Unterstrich (_) können kombiniert werden. Eine vollständige Beschreibung erhalten Sie in der C#-Sprachreferenz, die unter http://msdn.microsoft.com/vstudio/nextgen/technology/csharpdownload.asp heruntergeladen werden kann.

4    Siehe Kapitel 3, Schnelleinstieg in C#, Abschnitt »Grundlegende Datentypen«.

   

Visual C# 2012

Professionell entwickeln mit Visual C# 2012

Windows Presentation Foundation

Schrödinger programmiert C++

C++ Handbuch




Copyright © Rheinwerk Verlag GmbH 2001 - 2002
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, fon: 0228.42150.0, fax 0228.42150.77, service@rheinwerk-verlag.de