switch (C#-Referenz)switch (C# Reference)

switch ist eine Auswahlanweisung, die einen einzelnen switch-Abschnitt zum Ausführen aus einer Liste von Kandidaten auswählt, die auf einem Mustertreffer mit dem Vergleichsausdruck basiert.switch is a selection statement that chooses a single switch section to execute from a list of candidates based on a pattern match with the match expression.

using System;

public class Example
{
   public static void Main()
   {
      int caseSwitch = 1;
      
      switch (caseSwitch)
      {
          case 1:
              Console.WriteLine("Case 1");
              break;
          case 2:
              Console.WriteLine("Case 2");
              break;
          default:
              Console.WriteLine("Default case");
              break;
      }
   }
}
// The example displays the following output:
//       Case 1

Die Anweisung switch wird häufig als Alternative zu einem if-else-Konstrukt verwendet, wenn ein einzelner Ausdruck mit drei oder mehr Bedingungen getestet wird.The switch statement is often used as an alternative to an if-else construct if a single expression is tested against three or more conditions. Die folgende Anweisung switch bestimmt z.B., ob eine Variable des Typs Color einen von drei Werten hat:For example, the following switch statement determines whether a variable of type Color has one of three values:

using System;

public enum Color { Red, Green, Blue }

public class Example
{
   public static void Main()
   {
      Color c = (Color) (new Random()).Next(0, 3);
      switch (c)
      {
         case Color.Red:
            Console.WriteLine("The color is red");
            break;
         case Color.Green:
            Console.WriteLine("The color is green");
            break;
         case Color.Blue:
            Console.WriteLine("The color is blue");   
            break;
         default:
            Console.WriteLine("The color is unknown.");
            break;   
      }
   }
}

Dies entspricht dem folgenden Beispiel, das ein if-else-Konstrukt verwendet.It is equivalent to the following example that uses an if-else construct.

using System;

public enum Color { Red, Green, Blue }

public class Example
{
   public static void Main()
   {
      Color c = (Color) (new Random()).Next(0, 3);
      if (c == Color.Red)
         Console.WriteLine("The color is red");
      else if (c == Color.Green)
         Console.WriteLine("The color is green");
      else if (c == Color.Blue)
         Console.WriteLine("The color is blue");   
      else
         Console.WriteLine("The color is unknown.");
   }
}
// The example displays the following output:
//       The color is red

Der VergleichsausdruckThe match expression

Der Vergleichsausdruck stellt den Wert bereit, mit dem die Muster in den Bezeichnungen case verglichen werden.The match expression provides the value to match against the patterns in case labels. Die Syntax lautet:Its syntax is:

   switch (expr)

In C# 6 muss der Vergleichsausdruck ein Ausdruck sein, der einen Wert der folgenden Typen zurückgibt:In C# 6, the match expression must be an expression that returns a value of the following types:

Ab C# 7 kann der Vergleichsausdruck jeder Ausdruck sein, der nicht NULL ist.Starting with C# 7, the match expression can be any non-null expression.

Der switch-AbschnittThe switch section

Eine switch-Anweisung enthält eine oder mehrere switch-Abschnitte.A switch statement includes one or more switch sections. Jeder switch-Abschnitt enthält eine oder mehrere case-Bezeichnungen und eine Liste mit mindestens einer Anweisung.Each switch section contains one or more case labels followed by one or more statements. Das folgende Beispiel zeigt eine einfache switch-Anweisung, die über drei switch-Abschnitte verfügt.The following example shows a simple switch statement that has three switch sections. Jeder switch-Abschnitt enthält eine case-Bezeichnung, z. B. case 1:, und zwei Anweisungen.Each switch section has one case label, such as case 1:, and two statements.

Eine switch-Anweisung kann eine beliebige Anzahl von switch-Abschnitten enthalten, und jeder Abschnitt kann eine oder mehrere case-Bezeichnungen haben, wie im folgend Beispiel gezeigt wird.A switch statement can include any number of switch sections, and each section can have one or more case labels, as shown in the following example. Allerdings können zwei case-Bezeichnungen nicht denselben Ausdruck enthalten.However, no two case labels may contain the same expression.

using System;

public class Example
{
   public static void Main()
   {
      Random rnd = new Random();
      int caseSwitch = rnd.Next(1,4);
      
      switch (caseSwitch)
      {
          case 1:
              Console.WriteLine("Case 1");
              break;
          case 2:
          case 3:
              Console.WriteLine($"Case {caseSwitch}");
              break;
          default:
              Console.WriteLine($"An unexpected value ({caseSwitch})");
              break;
      }
   }
}
// The example displays output like the following:
//       Case 1

Nur ein switch-Abschnitt einer switch-Anweisung wir ausgeführt.Only one switch section in a switch statement executes. C# lässt nicht zu, dass die Ausführung von einem switch-Abschnitt zum nächsten fortgesetzt wird.C# does not allow execution to continue from one switch section to the next. Aus diesem Grund generiert der folgende Code den Compilerfehler CS0163: „Das Steuerelement kann nicht von einer case-Bezeichnung () zur nächsten fortfahren.“Because of this, the following code generates a compiler error, CS0163: "Control cannot fall through from one case label () to another."

switch (caseSwitch)  
{  
    // The following switch section causes an error.  
    case 1:  
        Console.WriteLine("Case 1...");  
        // Add a break or other jump statement here.  
    case 2:  
        Console.WriteLine("... and/or Case 2");  
        break;  
}  

Diese Anforderung wird normalerweise erfüllt, indem der switch-Abschnitt ausdrücklich durch Verwenden einer Anweisung break, goto oder return beendet wird.This requirement is usually met by explicitly exiting the switch section by using a break, goto, or return statement. Der folgende Code ist jedoch auch gültig, da er sicherstellt, dass die Programmsteuerung nicht im switch-Abschnitt default fortfährt.However, the following code is also valid, because it ensures that program control cannot fall through to the default switch section.

switch (caseSwitch)  
{  
    // The following switch section causes an error.  
    case 1:  
        Console.WriteLine("Case 1...");  
        break;  
    case 2:  
    case 3:
        Console.WriteLine("... and/or Case 2");  
        break;
    case 4:  
        while (true)  
           Console.WriteLine("Endless looping. . . ."); 
    default:
        Console.WriteLine("Default value...");
        break;                 
}  

Die Ausführung der Anweisungsliste im switch-Abschnitt mit einer case-Bezeichnung, die den Vergleichsausdruck vergleicht, beginnt mit der ersten Anweisung und durchläuft in der Regel die Anweisungsliste, bis eine jump-Anweisung erreicht wird, z.B. break, goto case, goto label, return oder throw.Execution of the statement list in the switch section with a case label that matches the match expression begins with the first statement and proceeds through the statement list, typically until a jump statement, such as a break, goto case, goto label, return, or throw, is reached. An diesem Punkt wird die Steuerung der switch-Anweisung entzogen oder an eine andere case-Bezeichnung übertragen.At that point, control is transferred outside the switch statement or to another case label. Eine goto-Anweisung muss bei Nichtverwendung die Steuerung an eine konstante Bezeichnung übergeben.A goto statement, if it is used, must transfer control to a constant label. Diese Einschränkung ist notwendig, da der Versuch, die Steuerung an eine nicht konstante Bezeichnung zu übergeben, unerwünschte Nebeneffekte haben kann, z.B. kann die Steuerung an eine nicht beabsichtigte Position im Code übergeben werden, oder es kann eine Endlosschleife entstehen.This restriction is necessary, since attempting to transfer control to a non-constant label can have undesirable side-effects, such transferring control to an unintended location in code or creating an endless loop.

case-BezeichnungenCase labels

Jede case-Bezeichnung gibt ein Muster an, mit dem der Vergleichsausdruck verglichen werden soll (die Variable caseSwitch in den vorherigen Beispielen).Each case label specifies a pattern to compare to the match expression (the caseSwitch variable in the previous examples). Wenn sie übereinstimmen, wird das Steuerelement an den switch-Abschnitt übertragen, der die erste übereinstimmende case-Bezeichnung enthält.If they match, control is transferred to the switch section that contains the first matching case label. Wenn keine case-Bezeichnung mit dem Vergleichsausdruck übereinstimmt, wird das Steuerelement an den Abschnitt mit der default-case-Bezeichnung übertragen, sofern vorhanden.If no case label pattern matches the match expression, control is transferred to the section with the default case label, if there is one. Wenn es kein default-case gibt, werden keine Anweisungen in jeglichen switch-Abschnitten ausgeführt, und ein Steuerelement wird außerhalb der switch-Anweisung übertragen.If there is no default case, no statements in any switch section are executed, and control is transferred outside the switch statement.

Informationen zur switch-Anweisung und zum Musterabgleich finden Sie im Abschnitt Musterabgleich mit der switch-Anweisung.For information on the switch statement and pattern matching, see the Pattern matching with the switch statement section.

Da C# 6 nur die Konstantenmuster unterstützt und die Wiederholung von Konstantenwerten nicht erlaubt, definieren case-Bezeichnungen exklusive Werte, und nur ein Muster kann mit dem Vergleichsausdruck übereinstimmen.Because C# 6 supports only the constant pattern and does not allow the repetition of constant values, case labels define mutually exclusive values, and only one pattern can match the match expression. Daher ist die Reihenfolge, in der die case-Anweisungen auftauchen, unwichtig.As a result, the order in which case statements appear is unimportant.

Da in C# 7 jedoch andere Muster unterstützt werden, müssen case-Bezeichnungen keine gegenseitig ausschließenden Werte definieren, und mehrere Muster können mit dem Vergleichsausdruck übereinstimmen.In C# 7, however, because other patterns are supported, case labels need not define mutually exclusive values, and multiple patterns can match the match expression. Da nur die Anweisungen im switch-Abschnitt ausgeführt werden, die das erste übereinstimmende Muster enthalten, ist die Reihenfolge, in der case-Anweisungen erscheinen, nun wichtig.Because only the statements in the switch section that contains the first matching pattern are executed, the order in which case statements appear is now important. Wenn C# einen switch-Abschnitt erkennt, dessen case-Anweisung oder Anweisungen eine Teilmenge der vorherigen Anweisungen ist oder einer entsprechen, erzeugt der Abschnitt den Compilerfehler CS8120: „Der Parameter wurde bereits von einem vorherigen Parameter verarbeitet.“If C# detects a switch section whose case statement or statements are equivalent to or are subsets of previous statements, it generates a compiler error, CS8120, "The switch case has already been handled by a previous case."

Das folgende Beispiel veranschaulicht eine switch-Anweisung, die eine Reihe von sich nicht gegenseitig ausschließenden Mustern verwendet.The following example illustrates a switch statement that uses a variety of non-mutually exclusive patterns. Wenn Sie den switch-Abschnitt case 0: verschieben, sodass er nicht länger der erste Abschnitt in der switch-Anweisung ist, erzeugt C# einen Compilerfehler, da eine Ganzzahl, deren Wert 0 ist, eine Teilmenge aller Ganzzahlen ist, die das Muster anhand der case int val-Anweisung definiert.If you move the case 0: switch section so that it is no longer the first section in the switch statement, C# generates a compiler error because an integer whose value is zero is a subset of all integers, which is the pattern defined by the case int val statement.

using System;
using System.Collections.Generic;
using System.Linq;

public class Example
{
   public static void Main()
   {
      var values = new List<object>();
      for (int ctr = 0; ctr <= 7; ctr++) {
         if (ctr == 2) 
            values.Add(DiceLibrary.Roll2());
         else if (ctr == 4)
            values.Add(DiceLibrary.Pass());
         else   
            values.Add(DiceLibrary.Roll());
      }   

      Console.WriteLine($"The sum of { values.Count } die is { DiceLibrary.DiceSum(values) }");
   }
}

public static class DiceLibrary
{
   // Random number generator to simulate dice rolls.
   static Random rnd = new Random();

   // Roll a single die.
   public static int Roll()
   {
      return rnd.Next(1, 7);
   }

   // Roll two dice.
   public static List<object> Roll2()
   {
      var rolls = new List<object>();      
      rolls.Add(Roll());
      rolls.Add(Roll());
      return rolls;
   }

   // Calculate the sum of n dice rolls.
   public static int DiceSum(IEnumerable<object> values)
   {
      var sum = 0;
      foreach (var item in values)
      {
            switch (item)
            {
               // A single zero value.
               case 0:
                  break;
               // A single value.
               case int val:
                  sum += val;
                  break;
               // A non-empty collection.
               case IEnumerable<object> subList when subList.Any():
                  sum += DiceSum(subList);
                  break;
               // An empty collection.
               case IEnumerable<object> subList:
                  break;
               //  A null reference.
               case null:
                  break;
               // A value that is neither an integer nor a collection.
               default:
                  throw new InvalidOperationException("unknown item type");
            }
      }
      return sum;
   }

   public static object Pass()
   {
      if (rnd.Next(0, 2) == 0)
         return null;
      else
         return new List<object>();
   }
}

Sie können dieses Problem beheben und die Compilerwarnung auf eine von zwei Arten entfernen:You can correct this issue and eliminate the compiler warning in one of two ways:

  • Durch das Ändern der Reihenfolge der switch-AbschnitteBy changing the order of the switch sections.

  • Durch das Verwenden einer </a name=“when“>when-Klausel in der case-BezeichnungBy using a when clause in the case label.

Der default-CaseThe default case

Der default-Case gibt den auszuführenden switch-Abschnitt an, wenn der Vergleichsausdruck nicht mit einer anderen case-Bezeichnung übereinstimmt.The default case specifies the switch section to execute if the match expression does not match any other case label. Wenn ein default-Case nicht vorhanden ist, und der Vergleichsausdruck nicht einer der anderen case-Bezeichnung entspricht, fährt der Programmablauf mit der switch-Anweisung fort.If a default case is not present and the match expression does not match any other case label, program flow falls through the switch statement.

Der default-Case kann in beliebiger Reihenfolge in der switch-Anweisung auftauchen.The default case can appear in any order in the switch statement. Unabhängig von der Reihenfolge im Quellcode wird er immer zuletzt ausgewertet, nachdem alle case-Bezeichnungen ausgewertet wurden.Regardless of its order in the source code, it is always evaluated last, after all case labels have been evaluated.

Musterabgleich mit der switch-Anweisung Pattern matching with the switch statement

Jede case-Anweisung definiert ein Muster, das, wenn es mit dem Vergleichsausdruck übereinstimmt, dafür sorgt, dass seine enthaltenden switch-Abschnitte ausgeführt werden.Each case statement defines a pattern that, if it matches the match expression, causes its containing switch section to be executed. Alle Versionen von C# unterstützen Konstantenmuster.All versions of C# support the constant pattern. Die übrigen Muster werden ab C# 7 unterstützt.The remaining patterns are supported beginning with C# 7.

KonstantenmusterConstant pattern

Das Konstantenmuster testet, ob der Vergleichsausdruck einer festgelegten Konstanten entspricht.The constant pattern tests whether the match expression equals a specified constant. Die Syntax lautet:Its syntax is:

   case constant:

wobei constant der zu testende Wert ist.where constant is the value to test for. constant kann eine der folgenden konstanten Ausdrücke sein:constant can be any of the following constant expressions:

  • Ein bool-Literal, entweder true oder falseA bool literal, either true or false.
  • Alle ganzzahligen Konstanten, z.B. int, lang oder ein ByteAny integral constant, such as an int, a long, or a byte.
  • Der Name einer deklarierten const-VariablenThe name of a declared const variable.
  • Eine Enumerationskonstante.An enumeration constant.
  • Ein char-LiteralA char literal.
  • Ein Zeichenfolgenliteral.A string literal.

Der Konstantenausdruck wird wie folgt ausgewertet:The constant expression is evaluated as follows:

  • Wenn expr und constant integrale Typen sind, bestimmt der C#-Gleichheitsoperator, ob der Ausdruck true (d.h., ob expr == constant) zurückgibt.If expr and constant are integral types, the C# equality operator determines whether the expression returns true (that is, whether expr == constant).

  • Andernfalls wird der Wert des Ausdrucks durch einen Aufruf der statischen Methode Object.Equals (expr, constant) bestimmt.Otherwise, the value of the expression is determined by a call to the static Object.Equals(expr, constant) method.

Das folgende Beispiel verwendet das Konstantenmuster, um zu bestimmen, ob ein bestimmtes Datum ein Wochenende, der erste Tag der Arbeitswoche, der letzte Tag der Arbeitswoche oder die Mitte der Arbeitswoche ist.The following example uses the constant pattern to determine whether a particular date is a weekend, the first day of the work week, the last day of the work week, or the middle of the work week. Es bewertet die Eigenschaft DateTime.DayOfWeek des heutigen Tags mit den Membern der DayOfWeek-Enumeration.It evaluates the DateTime.DayOfWeek property of the current day against the members of the DayOfWeek enumeration.

using System;

class Program
{
    static void Main()
    {
        switch (DateTime.Now.DayOfWeek)
        {
           case DayOfWeek.Sunday:
           case DayOfWeek.Saturday:
              Console.WriteLine("The weekend");
              break;
           case DayOfWeek.Monday:
              Console.WriteLine("The first day of the work week.");
              break;
           case DayOfWeek.Friday:
              Console.WriteLine("The last day of the work week.");
              break;
           default:
              Console.WriteLine("The middle of the work week.");
              break;   
        }
    }
}
// The example displays output like the following:
//       The middle of the work week.

Im folgenden Beispiel wird das Konstantenmuster verwendet, um Benutzereingaben in einer Konsolenanwendung zu steuern, die eine automatische Kaffeemaschine simuliert.The following example uses the constant pattern to handle user input in a console application that simulates an automatic coffee machine.

using System;

class Example
{
   static void Main()
   {
       Console.WriteLine("Coffee sizes: 1=small 2=medium 3=large");
       Console.Write("Please enter your selection: ");
       string str = Console.ReadLine();
       int cost = 0;

       // Because of the goto statements in cases 2 and 3, the base cost of 25
       // cents is added to the additional cost for the medium and large sizes.
       switch (str)
       {
          case "1":
          case "small":
              cost += 25;
              break;
          case "2":
          case "medium":
              cost += 25;
              goto case "1";
          case "3":
          case "large":
              cost += 50;
              goto case "1";
          default:
              Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
              break;
      }
      if (cost != 0)
      {
          Console.WriteLine("Please insert {0} cents.", cost);
      }
      Console.WriteLine("Thank you for your business.");
   }
}
// The example displays output like the following:
//         Coffee sizes: 1=small 2=medium 3=large
//         Please enter your selection: 2
//         Please insert 50 cents.
//         Thank you for your business.


TypmusterType pattern

Das Typmuster ermöglicht die präzise Auswertung und Konvertierung des Typs.The type pattern enables concise type evaluation and conversion. Wenn es mit der switch-Anweisung verwendet wird, um einen Musterabgleich auszuführen, wird getestet, ob eine Anweisung in einen bestimmten Typ konvertiert werden kann, und sofern dies möglich ist, wird es in eine Variable des Typs umgewandelt.When used with the switch statement to perform pattern matching, it tests whether an expression can be converted to a specified type and, if it can be, casts it to a variable of that type. Die Syntax lautet:Its syntax is:

   case type varname 

bei der Typ der Name des Typs ist, in den das Ergebnis von expr konvertiert wird, und varname das Objekt ist, in das das Ergebnis von expr konvertiert wird, wenn der Abgleich erfolgreich istwhere type is the name of the type to which the result of expr is to be converted, and varname is the object to which the result of expr is converted if the match succeeds.

Der case-Ausdruck ist true, wenn eine der folgenden Aussagen zutrifft:The case expression is true if any of the following is true:

  • expr ist eine Instanz des gleichen Typs wie Typ.expr is an instance of the same type as type.

  • expr ist eine Instanz eines Typs, der von Typ abgeleitet wird.expr is an instance of a type that derives from type. Das Ergebnis von expr kann, in anderen Worten, in eine Instanz von Typ umgewandelt werden.In other words, the result of expr can be upcast to an instance of type.

  • expr hat einen Kompilierzeittyp, der eine Basisklasse von type ist, und expr hat einen Laufzeittyp,der type ist oder von type abgeleitet wurde.expr has a compile-time type that is a base class of type, and expr has a runtime type that is type or is derived from type. Der Kompilierzeittyp einer Variablen ist der Typ der Variablen, wie es in der Deklaration des Typs definiert wurde.The compile-time type of a variable is the variable's type as defined in its type declaration. Der Laufzeittyp einer Variablen ist der Typ der Instanz, die dieser Variable zugewiesen wird.The runtime type of a variable is the type of the instance that is assigned to that variable.

  • expr ist eine Instanz eines Typs, der die Schnittstelle Typ implementiert.expr is an instance of a type that implements the type interface.

Wenn der case-Ausdruck TRUE ist, ist varname definitiv zugewiesen und hat nur innerhalb des switch-Abschnitts einen lokalen Geltungsbereich.If the case expression is true, varname is definitely assigned and has local scope within the switch section only.

Beachten Sie, dass null nicht mit einem Typ übereinstimmt.Note that null does not match a type. Verwenden Sie folgende case-Bezeichnung, um null abzugleichen:To match a null, you use the following case label:

case null:

Im folgenden Beispiel wird mithilfe des Typmusters Informationen über die verschiedenen Arten von Auflistungstypen bereitgestellt.The following example uses the type pattern to provide information about various kinds of collection types.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

class Example
{
    static void Main(string[] args)
    {
        int[] values = { 2, 4, 6, 8, 10 };
        ShowCollectionInformation(values);
        
        var names = new List<string>();
        names.AddRange( new string[] { "Adam", "Abigail", "Bertrand", "Bridgette" } );
        ShowCollectionInformation(names);

        List<int> numbers = null;
        ShowCollectionInformation(numbers);
    }
   
    private static void ShowCollectionInformation(object coll)
    {
        switch (coll)
        {
            case Array arr:
               Console.WriteLine($"An array with {arr.Length} elements.");
               break;
            case IEnumerable<int> ieInt:
               Console.WriteLine($"Average: {ieInt.Average(s => s)}");
               break;   
            case IList list:
               Console.WriteLine($"{list.Count} items");
               break;
            case IEnumerable ie:
               string result = "";
               foreach (var item in ie) 
                  result += "${e} ";
               Console.WriteLine(result);
               break;   
            case null:
               // Do nothing for a null.
               break;
            default:
               Console.WriteLine($"A instance of type {coll.GetType().Name}");
               break;   
        }
    }
}
// The example displays the following output:
//     An array with 5 elements.
//     4 items

Ohne Musterabgleich könnte dieser Code wie folgt geschrieben werden.Without pattern matching, this code might be written as follows. Die Verwendung des Typmusterabgleichs erzeugt einen kompakteren, lesbaren Code, indem nicht mehr getestet werden muss, ob das Ergebnis einer Umwandlung null ist, oder um wiederholte Umwandlungen auszuführen.The use of type pattern matching produces more compact, readable code by eliminating the need to test whether the result of a conversion is a null or to perform repeated casts.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

class Example
{
    static void Main(string[] args)
    {
        int[] values = { 2, 4, 6, 8, 10 };
        ShowCollectionInformation(values);
        
        var names = new List<string>();
        names.AddRange( new string[] { "Adam", "Abigail", "Bertrand", "Bridgette" } );
        ShowCollectionInformation(names);
        
        List<int> numbers = null;
        ShowCollectionInformation(numbers);
    }
   
    private static void ShowCollectionInformation(object coll)
    {
        if (coll is Array) {
           Array arr = (Array) coll;
           Console.WriteLine($"An array with {arr.Length} elements.");
        }
        else if (coll is IEnumerable<int>) {
            IEnumerable<int> ieInt = (IEnumerable<int>) coll;
            Console.WriteLine($"Average: {ieInt.Average(s => s)}");
        }
        else if (coll is IList) {
            IList list = (IList) coll;
            Console.WriteLine($"{list.Count} items");
        }
        else if (coll is IEnumerable) { 
            IEnumerable ie = (IEnumerable) coll;
            string result = "";
            foreach (var item in ie) 
               result += "${e} ";
            Console.WriteLine(result);
        }
        else if (coll == null) { 
            // Do nothing. 
        }
        else {
            Console.WriteLine($"An instance of type {coll.GetType().Name}");
        }   
    }
}
// The example displays the following output:
//     An array with 5 elements.
//     4 items

Die case-Anweisung und die when-KlauselThe case statement and the when clause

Da sich ab C# 7 case-Anweisungen nicht gegenseitig ausschließen müssen, können Sie eine when-Klausel hinzufügen, um eine zusätzliche Bedingung anzugeben, die erfüllt werden muss, damit die case-Anweisung als TRUE ausgewertet wird.Starting with C# 7, because case statements need not be mutually exclusive, you can use add a when clause to specify an additional condition that must be satisfied for the case statement to evaluate to true. Die when-Klausel kann ein beliebiger Ausdruck sein, der einen booleschen Wert zurückgibt.The when clause can be any expression that returns a Boolean value. Eine der häufigsten Verwendungsmöglichkeiten für die when-Klausel wird verwendet, um zu verhindern, dass ein switch-Abschnitt ausgeführt wird, wenn der Wert eines Ausdrucks mit null übereinstimmt.One of the more common uses for the when clause is used to prevent a switch section from executing when the value of a match expression is null.

Im folgenden Beispiel wird eine Shape-Basisklasse, eine Rectangle-Klasse, die von Shape abgeleitet wird, und eine Square-Klasse, die von Rectangle abgeleitet wird, definiert.The following example defines a base Shape class, a Rectangle class that derives from Shape, and a Square class that derives from Rectangle. Die when-Klausel wird verwendet, um sicherzustellen, dass ShowShapeInfo ein Rectangle-Objekt, dem eine gleiche Länge und Breite zugewiesen wurde, wie Square behandelt, selbst wenn es nicht als ein Square-Objekt instanziiert wurde.It uses the when clause to ensure that the ShowShapeInfo treats a Rectangle object that has been assigned equal lengths and widths as a Square even if is has not been instantiated as a Square object. Diese Methode versucht weder Informationen über ein Objekt anzuzeigen, das null ist, noch über eine Form, deren Bereich NULL ist.The method does not attempt to display information either about an object that is null or a shape whose area is zero.

using System;

public abstract class Shape
{
   public abstract double Area { get; }
   public abstract double Circumference { get; } 
}

public class Rectangle : Shape
{
   public Rectangle(double length, double width) 
   {
      Length = length;
      Width = width; 
   }

   public double Length { get; set; }
   public double Width { get; set; }
   
   public override double Area
   { 
      get { return Math.Round(Length * Width,2); } 
   } 
   
   public override double Circumference 
   {
      get { return (Length + Width) * 2; }
   }
}

public class Square : Rectangle
{
   public Square(double side) : base(side, side) 
   {
      Side = side; 
   }

   public double Side { get; set; }
}

public class Circle : Shape
{
   public Circle(double radius) 
   {
      Radius = radius;
   } 
   
   public double Radius { get; set; }

   public override double Circumference
   {
      get { return 2 * Math.PI * Radius; }
   }

   public override double Area
   {
      get { return Math.PI * Math.Pow(Radius, 2); } 
   }
}

public class Example
{
   public static void Main()
   {
      Shape sh = null;
      Shape[] shapes = { new Square(10), new Rectangle(5, 7),
                         sh, new Square(0), new Rectangle(8, 8),
                         new Circle(3) };
      foreach (var shape in shapes)
         ShowShapeInfo(shape);
   }

   private static void ShowShapeInfo(Shape sh)
   {
      switch (sh)
      {
         // Note that this code never evaluates to true.
         case Shape shape when shape == null:
            Console.WriteLine($"An uninitialized shape (shape == null)");
            break;
         case null:
            Console.WriteLine($"An uninitialized shape");
            break;
         case Shape shape when sh.Area == 0:
            Console.WriteLine($"The shape: {sh.GetType().Name} with no dimensions");
            break;
         case Square sq when sh.Area > 0:
            Console.WriteLine("Information about square:");
            Console.WriteLine($"   Length of a side: {sq.Side}");
            Console.WriteLine($"   Area: {sq.Area}");
            break;
         case Rectangle r when r.Length == r.Width && r.Area > 0:
            Console.WriteLine("Information about square rectangle:");
            Console.WriteLine($"   Length of a side: {r.Length}");
            Console.WriteLine($"   Area: {r.Area}");
            break;
         case Rectangle r when sh.Area > 0:
            Console.WriteLine("Information about rectangle:");
            Console.WriteLine($"   Dimensions: {r.Length} x {r.Width}");
            Console.WriteLine($"   Area: {r.Area}");
            break;
         case Shape shape when sh != null:
            Console.WriteLine($"A {sh.GetType().Name} shape");
            break;
         default:
            Console.WriteLine($"The {nameof(sh)} variable does not represent a Shape.");
            break;   
      }
   }
}
// The example displays the following output:
//       Information about square:
//          Length of a side: 10
//          Area: 100
//       Information about rectangle:
//          Dimensions: 5 x 7
//          Area: 35
//       An uninitialized shape
//       The shape: Square with no dimensions
//       Information about square rectangle:
//          Length of a side: 8
//          Area: 64
//       A Circle shape

Beachten Sie, dass in diesem Beispiel die when-Klausel, die zu prüfen versucht, ob ein Shape-Objekt null ist, nicht ausgeführt wird.Note that the when clause in the example that attempts to test whether a Shape object is null does not execute. Das richtige Typmuster, um auf null zu testen, ist case null:.The correct type pattern to test for a null is case null:.

C#-ProgrammiersprachenspezifikationC# Language Specification

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auchSee Also

C#-ReferenzC# Reference
C#-ProgrammierhandbuchC# Programming Guide
C#-SchlüsselwörterC# Keywords
if-elseif-else
MustervergleichPattern Matching