przełącznik (C# odwołanie)switch (C# reference)

switch jest instrukcją wyboru, która wybiera pojedynczy przełącznik , który ma zostać wykonany z listy kandydatów na podstawie dopasowania wzorca z wyrażeniem Match.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

Instrukcja switch jest często używana jako alternatywa dla konstrukcji if-else , jeśli pojedyncze wyrażenie jest testowane w oparciu o trzy lub więcej warunków.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. Na przykład następująca instrukcja switch określa, czy zmienna typu Color ma jedną z trzech wartości: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;   
      }
   }
}

Jest to odpowiednik poniższego przykładu korzystającego z if-else konstrukcja.It's 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

Wyrażenie dopasowaniaThe match expression

Wyrażenie Match zawiera wartość do dopasowania względem wzorców w etykietach case.The match expression provides the value to match against the patterns in case labels. Jego składnia to:Its syntax is:

   switch (expr)

W C# 6 i wcześniejszych wyrażenia dopasowania musi być wyrażeniem zwracającym wartość następujących typów:In C# 6 and earlier, the match expression must be an expression that returns a value of the following types:

Począwszy od C# 7,0, wyrażenie dopasowania może być dowolnym wyrażeniem o wartości innej niż null.Starting with C# 7.0, the match expression can be any non-null expression.

Sekcja SwitchThe switch section

Instrukcja switch zawiera jedną lub więcej sekcji przełączników.A switch statement includes one or more switch sections. Każda sekcja przełącznika zawiera jedną lub więcej etykiet przypadków (literę lub etykietę domyślną), po której następuje jedna lub więcej instrukcji.Each switch section contains one or more case labels (either a case or default label) followed by one or more statements. Instrukcja switch może zawierać co najwyżej jedną etykietę domyślną umieszczoną w dowolnej sekcji Switch.The switch statement may include at most one default label placed in any switch section. Poniższy przykład pokazuje prostą instrukcję switch, która ma trzy sekcje przełączników, z których każda zawiera dwie instrukcje.The following example shows a simple switch statement that has three switch sections, each containing two statements. Druga sekcja Switch zawiera etykiety case 2: i case 3:.The second switch section contains the case 2: and case 3: labels.

Instrukcja switch może zawierać dowolną liczbę sekcji przełączników, a Każda sekcja może mieć jedną lub więcej etykiet wielkości liter, jak pokazano w poniższym przykładzie.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. Jednak żadne dwie etykiety wielkości liter nie mogą zawierać tego samego wyrażenia.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

W instrukcji switch jest wykonywana tylko jedna sekcja Switch.Only one switch section in a switch statement executes. C#nie zezwala na kontynuowanie wykonywania z jednej sekcji przełącznika do następnej.C# doesn't allow execution to continue from one switch section to the next. W związku z tym Poniższy kod generuje błąd kompilatora, CS0163: "kontrolka nie może przechodzić z jednej etykiety case (<etykieta przypadku >) do innej".Because of this, the following code generates a compiler error, CS0163: "Control cannot fall through from one case label (<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;
}

To wymaganie jest zwykle spełnione przez jawne opuszczenie sekcji Switch za pomocą instrukcji Break, gotolub Return .This requirement is usually met by explicitly exiting the switch section by using a break, goto, or return statement. Jednak następujący kod jest również prawidłowy, ponieważ gwarantuje, że formant programu nie przechodzi do sekcji przełącznika default.However, the following code is also valid, because it ensures that program control can't fall through to the default switch section.

switch (caseSwitch)  
{
    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;                 
}  

Wykonanie listy instrukcji w sekcji Switch z etykietą Case, która pasuje do wyrażenia Match rozpoczyna się od pierwszej instrukcji i przechodzi przez listę instrukcji, zwykle do momentu, aż do instrukcji skoku, takiej jak break, goto case``goto label, returnlub throw, zostanie osiągnięty.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. W tym momencie kontrola jest przekazywana poza instrukcją switch lub do innej etykiety case.At that point, control is transferred outside the switch statement or to another case label. Instrukcja goto, jeśli jest używana, musi przekazywać kontrolę do stałej etykiety.A goto statement, if it's used, must transfer control to a constant label. To ograniczenie jest konieczne, ponieważ próba przetransferowania kontroli do etykiety niestałej może mieć niepożądane efekty uboczne, takie przeniesienie kontroli do niezamierzonej lokalizacji w kodzie lub utworzenie pętli nieskończonej.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.

Etykiety przypadkuCase labels

Każda etykieta przypadku określa wzorzec do porównania z wyrażeniem dopasowania (zmienna caseSwitch w poprzednich przykładach).Each case label specifies a pattern to compare to the match expression (the caseSwitch variable in the previous examples). Jeśli są one zgodne, sterowanie jest przekazywane do sekcji Switch, która zawiera pierwszą pasującą etykietę case.If they match, control is transferred to the switch section that contains the first matching case label. Jeśli żaden wzorzec etykiety case nie jest zgodny z wyrażeniem Match, formant jest przenoszony do sekcji z etykietą przypadku default, jeśli istnieje.If no case label pattern matches the match expression, control is transferred to the section with the default case label, if there's one. Jeśli nie ma defaultj wielkości liter, nie są wykonywane żadne instrukcje w żadnej sekcji Switch, a kontrolka jest transferowana poza instrukcją switch.If there's no default case, no statements in any switch section are executed, and control is transferred outside the switch statement.

Aby uzyskać informacje na temat instrukcji switch i dopasowania do wzorca, zobacz Zgodność wzorców z sekcją switch instrukcji .For information on the switch statement and pattern matching, see the Pattern matching with the switch statement section.

Ponieważ C# 6 obsługuje tylko wzorce stałe i nie zezwala na powtarzanie wartości stałych, etykiety przypadków definiują wzajemnie wykluczające się wartości, a tylko jeden wzorzec może być zgodny z wyrażeniem Match.Because C# 6 supports only the constant pattern and doesn't allow the repetition of constant values, case labels define mutually exclusive values, and only one pattern can match the match expression. W związku z tym kolejność, w której pojawiają się instrukcje case, jest nieważna.As a result, the order in which case statements appear is unimportant.

W C# 7,0, jednak ponieważ inne wzorce są obsługiwane, etykiety przypadków nie muszą definiować wzajemnie wykluczających się wartości, a wiele wzorców może pasować do wyrażenia Match.In C# 7.0, however, because other patterns are supported, case labels need not define mutually exclusive values, and multiple patterns can match the match expression. Ponieważ są wykonywane tylko instrukcje w pierwszej sekcji przełącznika, które zawiera pasujący wzorzec, kolejność, w której pojawiają się instrukcje case, jest teraz ważna.Because only the statements in the first switch section that contains the matching pattern are executed, the order in which case statements appear is now important. Jeśli C# program wykryje sekcję Switch, której instrukcją Case lub instrukcje są równoważne lub są podzbiorami poprzednich instrukcji, generuje błąd kompilatora, CS8120, "przypadek przełączania został już obsłużony przez poprzednią literę".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."

Poniższy przykład ilustruje instrukcję switch, która używa różnych niewzajemnie wykluczających się wzorców.The following example illustrates a switch statement that uses a variety of non-mutually exclusive patterns. Jeśli przeniesiesz sekcję Switch case 0: tak, aby nie była już pierwszą sekcją w instrukcji switch, program C# generuje błąd kompilatora, ponieważ liczba całkowita, której wartością jest zero, jest podzbiorem wszystkich liczb całkowitych, które jest wzorcem zdefiniowanym przez instrukcję case int val .If you move the case 0: switch section so that it's 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>();
   }
}

Możesz rozwiązać ten problem i wyeliminować Ostrzeżenie kompilatora na jeden z dwóch sposobów:You can correct this issue and eliminate the compiler warning in one of two ways:

  • Zmieniając kolejność sekcji Switch.By changing the order of the switch sections.

  • Za pomocą klauzuli when w etykiecie case.By using a when clause in the case label.

default przypadkuThe default case

default Case określa sekcję Switch, która ma zostać wykonana, jeśli wyrażenie Match nie pasuje do żadnej innej etykiety case.The default case specifies the switch section to execute if the match expression doesn't match any other case label. Jeśli default przypadku nie istnieje i wyrażenie Match nie jest zgodne z żadną inną etykietą case, przepływ programu odbywa się za pomocą instrukcji switch.If a default case is not present and the match expression doesn't match any other case label, program flow falls through the switch statement.

Przypadek default może występować w dowolnej kolejności w instrukcji switch.The default case can appear in any order in the switch statement. Bez względu na jego kolejność w kodzie źródłowym jest zawsze Szacowana jako Ostatnia, po ocenie wszystkich etykiet case.Regardless of its order in the source code, it's always evaluated last, after all case labels have been evaluated.

dopasowywania do wzorca przy użyciu instrukcji switch Pattern matching with the switch statement

Każda instrukcja case definiuje wzorzec, który jest zgodny z wyrażeniem Match, powoduje, że jego sekcja Switch zostanie wykonana.Each case statement defines a pattern that, if it matches the match expression, causes its containing switch section to be executed. Wszystkie wersje programu C# obsługują stałe wzorce.All versions of C# support the constant pattern. Pozostałe wzorce są obsługiwane począwszy od C# 7,0.The remaining patterns are supported beginning with C# 7.0.

Wzorzec stałejConstant pattern

Wzorzec stałej testuje, czy wyrażenie dopasowania jest równe określonej stałej.The constant pattern tests whether the match expression equals a specified constant. Jego składnia to:Its syntax is:

   case constant:

gdzie stała jest wartością do przetestowania.where constant is the value to test for. stała może być dowolnym z następujących wyrażeń stałych:constant can be any of the following constant expressions:

  • Literał bool , true lub false.A bool literal, either true or false.
  • Dowolna stała całkowita, taka jak int, Longlub Byte.Any integral constant, such as an int, a long, or a byte.
  • Nazwa zadeklarowanej zmiennej const.The name of a declared const variable.
  • Stała wyliczenia.An enumeration constant.
  • Literał znakowy .A char literal.
  • Literał ciągu .A string literal.

Wyrażenie stałe jest oceniane w następujący sposób:The constant expression is evaluated as follows:

  • Jeśli wyrażenie i stała są typami całkowitymi, C# operator równości określa, czy wyrażenie zwróci true (to znaczy czy expr == constant).If expr and constant are integral types, the C# equality operator determines whether the expression returns true (that is, whether expr == constant).

  • W przeciwnym razie wartość wyrażenia jest określana przez wywołanie metody static obiektu. Equals (wyrażenie, stała) .Otherwise, the value of the expression is determined by a call to the static Object.Equals(expr, constant) method.

W poniższym przykładzie za pomocą wzorca stałego można określić, czy konkretna data to weekend, pierwszy dzień tygodnia pracy, ostatni dzień tygodnia pracy lub środek tygodnia pracy.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. Oblicza Właściwość DateTime.DayOfWeek bieżącego dnia względem elementów członkowskich wyliczenia DayOfWeek.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.

Poniższy przykład używa wzorca stałego do obsługi danych wejściowych użytkownika w aplikacji konsolowej, która symuluje automatyczną maszynę Kawową.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.


Wzorzec typuType pattern

Wzorzec typu umożliwia obliczanie i konwersję zwięzłego typu.The type pattern enables concise type evaluation and conversion. Gdy jest używany z instrukcją switch, aby wykonać dopasowanie do wzorca, sprawdza, czy wyrażenie można przekonwertować na określony typ, i, jeśli to możliwe, rzutuje go na zmienną tego typu.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. Jego składnia to:Its syntax is:

   case type varname

Where Type jest nazwą typu, do którego zostanie przekonwertowany wynik wyrażenia , a nazwa_zmiennej jest obiektem, do którego zostanie przekonwertowany wynik wyrażenia , jeśli dopasowanie się powiedzie.where 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. Typ "czas kompilacji" wyrażenia może być parametrem typu ogólnego, rozpoczynając od C# 7,1.The compile-time type of expr may be a generic type parameter, starting with C# 7.1.

Wyrażenie case jest true, jeśli którykolwiek z następujących warunków jest spełniony:The case expression is true if any of the following is true:

  • wyrażenie jest wystąpieniem tego samego typu co Typ.expr is an instance of the same type as type.

  • wyrażenie jest wystąpieniem typu, który pochodzi od typu.expr is an instance of a type that derives from type. Innymi słowy, wynik wyrażenia może być rzutowany na wystąpienie typu.In other words, the result of expr can be upcast to an instance of type.

  • wyrażenie ma typ czasu kompilacji, który jest klasą bazową typu, a wyrażenie ma typ środowiska uruchomieniowego, który jest typem lub pochodzi od typu.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. Typ czasu kompilacji zmiennej to typ zmiennej, zgodnie z definicją w deklaracji typu.The compile-time type of a variable is the variable's type as defined in its type declaration. Typ środowiska uruchomieniowego zmiennej to typ wystąpienia, które jest przypisane do tej zmiennej.The runtime type of a variable is the type of the instance that is assigned to that variable.

  • wyrażenie jest wystąpieniem typu, który implementuje interfejs typu .expr is an instance of a type that implements the type interface.

Jeśli wyrażenie CASE ma wartość true, właściwość nazwa_zmiennej jest ostatecznie przypisana i ma zakres lokalny tylko w sekcji Switch.If the case expression is true, varname is definitely assigned and has local scope within the switch section only.

Należy zauważyć, że null nie pasuje do typu.Note that null doesn't match a type. Aby dopasować null, należy użyć następującej etykiety case:To match a null, you use the following case label:

case null:

Poniższy przykład używa wzorca typu, aby podać informacje dotyczące różnych rodzajów typów kolekcji.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 e 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

Zamiast objectmożna utworzyć metodę rodzajową przy użyciu typu kolekcji jako parametru typu, jak pokazano w poniższym kodzie:Instead of object, you could make a generic method, using the type of the collection as the type parameter, as shown in the following code:

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<T>(T 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 e in ie) 
                  result += "${e} ";
               Console.WriteLine(result);
               break;   
            case object o:
               Console.WriteLine($"A instance of type {o.GetType().Name}");
               break;   
            default:
                Console.WriteLine("Null passed to this method.");
                break;
        }
    }
}
// The example displays the following output:
//     An array with 5 elements.
//     4 items
//     Null passed to this method.

Wersja ogólna różni się od pierwszej próbki na dwa sposoby.The generic version is different than the first sample in two ways. Najpierw nie można użyć przypadku null.First, you can't use the null case. Nie można użyć żadnego ze stałych przypadków, ponieważ kompilator nie może konwertować dowolnego dowolnego typu T na dowolny typ inny niż object.You can't use any constant case because the compiler can't convert any arbitrary type T to any type other than object. Co było default przypadku teraz testuje objecto wartości innej niż null.What had been the default case now tests for a non-null object. Oznacza to, że default testy przypadku null.That means the default case tests only for null.

Bez dopasowania do wzorca ten kod może być zapisany w następujący sposób.Without pattern matching, this code might be written as follows. Użycie dopasowania wzorca typu daje bardziej zwarty, czytelny kod, eliminując konieczność sprawdzenia, czy wynik konwersji jest null, czy też do wykonywania powtarzających się rzutowania.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 e 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

instrukcji case i klauzuli when The case statement and the when clause

Począwszy od C# 7,0, ponieważ instrukcje Case nie muszą się wzajemnie wykluczać, można dodać klauzulę when, aby określić dodatkowy warunek, który musi być spełniony dla instrukcji case, aby obliczyć wartość true.Starting with C# 7.0, because case statements need not be mutually exclusive, you can add a when clause to specify an additional condition that must be satisfied for the case statement to evaluate to true. Klauzula when może być dowolnym wyrażeniem zwracającym wartość logiczną.The when clause can be any expression that returns a Boolean value.

W poniższym przykładzie zdefiniowano klasę podstawową Shape, klasy Rectangle, która pochodzi od Shapei klasy Square, która pochodzi od Rectangle.The following example defines a base Shape class, a Rectangle class that derives from Shape, and a Square class that derives from Rectangle. Używa klauzuli when, aby upewnić się, że ShowShapeInfo traktuje Rectangle obiekt, do którego przypisano równe długości i szerokości jako Square nawet wtedy, gdy nie został skonkretyzowany jako obiekt Square.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 it hasn't been instantiated as a Square object. Metoda nie próbuje wyświetlić informacji o obiekcie null lub kształcie, którego obszar ma wartość zero.The method doesn't 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

Należy zauważyć, że klauzula when w przykładzie, która próbuje sprawdzić, czy obiekt Shape jest null nie jest wykonywany.Note that the when clause in the example that attempts to test whether a Shape object is null doesn't execute. Poprawna wzorzec typu do testowania dla null jest case null:.The correct type pattern to test for a null is case null:.

specyfikacja języka C#C# language specification

Aby uzyskać więcej informacji, zobacz instrukcję Switch w C# specyfikacji języka.For more information, see The switch statement in the C# Language Specification. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.The language specification is the definitive source for C# syntax and usage.

Zobacz takżeSee also