Startseite  Index  <<  >>  

9 - Aufzählungstypen

Wenn Sie in bestimmten Situationen nur einige wenige Werte zulassen möchten oder bei einer Parameterübergabe an eine Funktion deren Arbeitsweise steuern wollen, können Sie dies natürlich durch die Übergabe einer Zahl, z.B. vom Typ int, und Auswertung dieses Wertes tun. Das hat aber mehrere Nachteile:

  • Sie können nicht automatisch sicherstellen, dass der übergebene Wert einem der von Ihnen verarbeiteten Werte entspricht.
  • Bei der Übergabe eines solchen Wertes an eine Methode wissen Sie nicht, welche Werte zugelassen sind (bzw. erhalten keine Hilfe zu den möglichen Parameterwerten).
  • Der Wert selbst hat keine Aussagekraft. Eine Übergabe des Wertes 5 sagt Ihnen z.B. nicht, welche Bedeutung dieser Wert hat.

    Beispiel: Steuerung über einfache Zahlen

    Die Methode Ausgabe() führt abhängig vom übergebenen Wert des Parameters modus eine andere Aktion aus. Da aber beliebige int-Werte zur Übergabe erlaubt sind, kann sich auch einmal ein ungültiger Wert einschleichen. Dies kann aber beispielsweise der Compiler nicht feststellen. Außerdem kann man keine Beziehung vom übergebenen Wert 2 an die Methode Ausgabe() herstellen.

    void Ausgabe(int modus)
    {
      switch(modus)
      {
        case 0: // tue dies;
                break;
        case 1: // tue das;
                break;
      }
    }
    ...
    Ausgabe(2);

    Nutzen von Aufzählungstypen
    Aufzählungstypen (auch als Enumerationen oder kurz Aufzählungen bezeichnet) bieten eine bessere Lösung, indem sie Typsicherheit und Lesbarkeit verbessern. Aufzählungen sind wie Klassen Typen und können damit an den gleichen Stellen eingesetzt werden. Sie werden über das Schlüsselwort enum deklariert und enthalten eine oder mehrere Aufzählungskonstanten.

    Beispiel: Steuerung über Aufzählungstypen

    Das eben gezeigte Beispiel ließe sich mit Aufzählungstypen folgendermaßen implementieren. Zuerst wird eine Aufzählung mit dem Namen Aktion deklariert. Diese besteht aus drei Konstanten. Als Parameter wird nun kein int-Wert, sondern ein Wert vom Typ Aktion an die Methode übergeben. Beim Aufruf der Methode muss eine der Aufzählungskonstanten übergeben werden. Jetzt kann der Compiler tatsächlich prüfen, dass nur eine der definierten Konstanten übergeben wurde. Auch innerhalb der switch-Anweisung in der Methode Ausgabe() können nun direkt die Aufzählungskonstanten verwendet werden. Dies ist wesentlich sprechender als einfache Zahlenwerte.

    enum Aktion { Loeschen, Einfuegen, Aendern };
    void Ausgabe(Aktion modus)
    {
      switch(modus)
      {
        case Aktion.Loeschen:  // tue dies;
                               break;
        case Aktion.Einfuegen: // tue das;
                               break;
      }
    }
    ...
    Ausgabe(Aktion.Einfuegen);

    Syntax
  • Aufzählungstypen werden mit dem Schlüsselwort enum deklariert.
  • Danach folgt ein Bezeichner und anschließend in geschweiften Klammern die Aufzählungskonstanten (ohne Anführungszeichen). Die Konstanten werden durch Komma voneinander getrennt. Die Deklaration wird optional durch ein Semikolon abgeschlossen.
  • Den Konstanten können Sie Initialwerte zuweisen, die im verwendeten Wertebereich des Aufzählungstyps liegen müssen. Standardmäßig haben die Konstanten den Typ und den Wertebereich von int.
  • Konstanten, denen Sie explizit keinen Wert zuweisen, werden automatisch mit einem Wert versehen. Das erste Element erhält den Wert 0, das darauf folgende den Wert 1 usw. Haben Sie zwischendurch selbst einer Konstanten einen Wert zugewiesen, erhält das nächste Element einen um 1 höheren Wert. Dadurch kann es auch vorkommen, dass mehrere Konstanten (automatisch) mit den gleichen Werten versehen werden.
  • Wenn Sie den Konstanten selbst Werte zuweisen, müssen Sie auf keine Reihenfolge bei der Wertvergabe achten. Sie können z.B. der ersten Konstante den Wert 5 und der zweiten den Wert 3 zuweisen.
  • Konstanten können wie bereits erwähnt auch dieselben Werte besitzen. Damit können mehrere Konstanten zur Beschreibung desselben Sachverhalts verwendet werden.

    Beispiel: Probleme bei gemeinsamen Konstantenwerten

    Einer Konstante kann der Wert einer anderer Konstante zugewiesen werden, wenn diese Konstante bereits ihren Wert besitzt (1. Zeile). In der zweiten Zeile entsteht allerdings eine zirkuläre Referenz, da Wert1 von Wert2 abhängt und Wert2 implizit von Wert1 (sie erhält ja den um 1 höheren Wert als Wert1).
    enum Daten { Wert1, Wert2, Wert3 = Wert1 }
    enum Daten { Wert1 = Wert2, Wert2 }
    enum Daten { Wert1 = 1, Wert2, Wert3 = Wert1 }

    Beispiel: Konfigurieren der Anzeige über Aufzählungskonstanten

    Auch wenn es "nur" eine Konsolenanwendung ist, soll diese farblich konfigurierbar gemacht werden. Dazu werden drei Farbschemas definiert. Diese Farbschemas werden als Auszählungskonstanten in der Aufzählung FarbSchema deklariert. Die Methode SetFarbSchema() übernimmt als Parameter das ausgewählte Farbschema und setzt die Vorder- und Hintergrundfarbe der Konsole entsprechend des gewählten Farbschemas auf die vordefinierten Werte. Zum Setzen dieser Werte dienen Eigenschaften der Klasse Console. Damit die Einstellungen sofort für den Inhalt des gesamten Konsolenfensters aktiv werden, wird zum Abschluss der Inhalt des Fensters durch den Aufruf von Clear() gelöscht. Der Hintergrund wird dann in der neu eingestellten Farbe gezeigt.

    Die Konfiguration von Konsolenanwendungen wird später noch in einem eigenen Kapitel (kurz) besprochen.

    using System;
    namespace CSharpBuch.Kap09
    {
      public enum FarbSchema { Ocean, Normal, Pink };
      
      public class EinfacheAufzaehlungen
      {
        static void Main(string[] args)
        {
          FarbSchema fs = FarbSchema.Ocean;
          SetFarbSchema(fs);
          Console.WriteLine("Ausgewähltes Farbschema ..." + fs.ToString());
          Console.ReadLine();
        }
        static void SetFarbSchema(FarbSchema fs)
        {
          switch(fs)
          {
            case FarbSchema.Normal: 
                   Console.BackgroundColor = ConsoleColor.Black;
                   Console.ForegroundColor = ConsoleColor.White;
                   break;
            case FarbSchema.Ocean:  
                   Console.BackgroundColor = ConsoleColor.Blue;
                   Console.ForegroundColor = ConsoleColor.Yellow;
                   break;
            case FarbSchema.Pink:   
                   Console.BackgroundColor = ConsoleColor.Black;
                   Console.ForegroundColor = ConsoleColor.White;
                   break;
          }
          Console.Clear();
        }
      }
    }
    Listing 9.1: EinfacheAufzaehlungen.cs

    9.2 Basistyp des Aufzählungstypen setzen

    Standardmäßig haben alle Konstanten eines Aufzählungstyps den Typ int. Sie können aber auch einen anderen ganzzahligen Typ, außer char, angeben. Anwendungsgebiete sind Speicherplatzersparnis und die Vereinfachung der Weiterverarbeitung, wenn die Konstanten später in einem anderen Typ als int benötigt werden. Wenn Sie auf den numerischen Wert einer Aufzählungskonstante zugreifen wollen, müssen Sie in jedem Fall einen Cast in den gewünschten Typ vornehmen.

    Beispiel: Basistyp einer Aufzählung definieren

    Als Basistyp der Aufzählung Wochentage wird der Datentyp byte verwendet. Durch einen Cast kann der numerische Wert einer Aufzählungskonstante, hier Mo, ermittelt werden.
    enum Wochentage: byte { Mo, Di, Mi, Do, Fr, Sa, So };
    ...
    byte b = (byte)Wochentage.Mo;

    9.3 Die Struktur Enum

    Wenn Sie einen Aufzählungstyp deklarieren, wird dieser implizit von der Struktur Enum abgeleitet. Ein Aufzählungstyp erbt dadurch aber keine neuen Methoden (außer natürlich den Methoden der Klasse Object). Sie können aber die statischen Methoden der Struktur Enum nutzen, denen Sie den Aufzählungstyp in Form eines Type-Parameters übergeben (typeof(Aufzählungstyp)).
    MethodeBeschreibung
    Format()Formatiert eine Konstante in einen vorgegebenen Typ. Das Ausgabeformat ist als zweiter Parameter anzugeben.
    GetName()
    GetNames()
    Liefert den bzw. die Namen (Bezeichner) einer oder aller Konstanten einer Aufzählung.
    GetUnderlyingType()Liefert den Basistyp der Aufzählung zurück, z.B. int oder byte.
    GetValues()Liefert die numerischen Werte der Konstanten zurück.
    IsDefined()Liefert einen booleschen Wert, der angibt, ob eine Konstante, deren Name als string übergeben wird, in einer Aufzählung vorhanden ist.
    Parse()Liefert eine Aufzählungskonstante aufgrund des übergebenen Bezeichners zurück.
    Tabelle 9.1: Ausgewählte Methoden der Struktur Enum

    INFO

    Beachten Sie, dass die Methoden GetNames() und GetValues() nicht immer die Reihenfolge der Konstanten widerspiegeln, wie sie in der Typdefinition der Aufzählung verwendet wird.

    Beispiel: Auswerten einer Auflistung über die Struktur Enum

    In diesem Beispiel werden die Methoden der Struktur Enum verwendet, um Informationen zu der Aufzählung FarbSchema zu erhalten (die diesmal etwas anders deklariert wurde). Auf diese Weise können Sie also auch Aufzählungen dynamisch auswerten, die Sie eventuell über fremde Bibliotheken bezogen haben. Eine größere Bedeutung kommt aber z.B. der Tatsache zu, dass sich bei Änderung der Aufzählungskonstanten (neue hinzufügen, Vergabe von Vorgabewerten etc.) die Werte der Aufzählungskonstanten ändern können. Dies können Sie nun feststellen und gegebenenfalls darauf reagieren.

    using System;
    namespace CSharpBuch.Kap09
    {
      enum FarbSchema: byte { Ocean = 0, Normal = 3, Pink }
    
      public class SpezialAufzaehlungen
      {
        static void Main(string[] args)
        {
          FarbSchema fs = FarbSchema.Pink;
          Console.WriteLine("Methoden der Strukur Enum ...");
          Console.WriteLine("Format(): " + Enum.Format(typeof(FarbSchema), FarbSchema.Ocean, "G"));
          Console.WriteLine("GetName(): " + Enum.GetName(typeof(FarbSchema), fs));
          Console.WriteLine("Get(): " + Enum.GetUnderlyingType(typeof(FarbSchema)));
          if(Enum.IsDefined(typeof(FarbSchema), "Pink"))
          {
            Console.WriteLine("IsDefined(): Pink gibt's in FarbSchema");
            FarbSchema fs2 = (FarbSchema)Enum.Parse(typeof(FarbSchema), "Pink");
          }
    
          Console.WriteLine("\nAlle Namen der Aufzählungskonstanten: ");
          foreach(string s in Enum.GetNames(typeof(FarbSchema)))
            Console.WriteLine(s);
     
          Console.WriteLine("\nAlle Werte der Aufzählungskonstanten: ");
          foreach(byte b in Enum.GetValues(typeof(FarbSchema)))
            Console.WriteLine(b);
        }
      }
    }
    Listing 9.2: SpezialAufzaehlungen.cs

    9.4 Übungsaufgaben

    Aufgabe 1
    Deklarieren Sie einen Aufzählungstyp für die vier Operationen Addition, Subtraktion, Multiplikation und Division. Stellen Sie des Weiteren eine Methode bereit, die einen Parameter vom Typ dieser Aufzählung sowie zwei Parameter vom Typ int erwartet. Führen Sie in dieser Methode, abhängig vom übergebenen Wert, die zur Aufzählungskonstante passende Operation aus und geben Sie das Ergebnis zurück.

    Verwenden Sie als Basistyp der Aufzählung den Typ byte.
    Aufgabe 2
    Stellen Sie über eine Konsolenanwendung eine Menüauswahl bereit, welche die Auswahl einer der Operationen aus Aufgabe 1 ermöglicht. Geben Sie dazu die Bezeichner der Aufzählungskonstanten aus, verarbeiten Sie die Eingabe (Operation auswählen und zwei Zahlen eingeben) und geben Sie das Ergebnis aus.