switch(C# 참조)switch (C# reference)

switch일치 식을 사용한 패턴 일치를 기반으로 하여 후보 목록에서 실행할 switch 섹션 하나를 선택하는 선택 문입니다.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

단일 식을 3개 이상의 조건에 대해 테스트하는 경우 switch 문이 if-else 구문 대신 사용되는 경우가 많습니다.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. 예를 들어 다음 switch 문은 Color 형식의 변수에 다음 세 가지 값 중 하나가 있는지 여부를 확인합니다.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;   
      }
   }
}

이 문은 if-else 구문을 사용하는 다음 예제와 같습니다.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

일치 식The match expression

일치 식은 case 레이블의 패턴과 일치시킬 값을 제공합니다.The match expression provides the value to match against the patterns in case labels. 사용되는 구문은 다음과 같습니다.Its syntax is:

   switch (expr)

C# 6 이하에서 일치 식은 다음 형식의 값을 반환하는 식이어야 합니다.In C# 6 and earlier, the match expression must be an expression that returns a value of the following types:

C# 7.0부터 일치 식은 null이 아닌 모든 식일 수 있습니다.Starting with C# 7.0, the match expression can be any non-null expression.

switch 섹션The switch section

switch 문에는 스위치 섹션이 하나 이상 포함됩니다.A switch statement includes one or more switch sections. 각 switch 섹션에는 하나 이상의 case 레이블(사례 또는 기본 레이블) 및 하나 이상의 명령문이 있습니다.Each switch section contains one or more case labels (either a case or default label) followed by one or more statements. switch 문은 switch 섹션에 있는 기본 레이블이 하나만 포함될 수 있습니다.The switch statement may include at most one default label placed in any switch section. 다음 예제에서는 각각 두 개의 명령문을 포함하는 세 개의 switch 섹션이 있는 간단한 switch 문을 보여 줍니다.The following example shows a simple switch statement that has three switch sections, each containing two statements. 두 번째 switch 섹션에는 case 2:case 3: 레이블이 포함되어 있습니다.The second switch section contains the case 2: and case 3: labels.

switch 문에 포함할 수 있는 switch 섹션 수에는 제한이 없으며 각 섹션에 하나 이상의 case 레이블을 포함할 수 있습니다(다음 예제 참조).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. 하지만 두 case 레이블에 동일한 식을 포함할 수는 없습니다.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

switch 문에서 하나의 switch 섹션만 실행됩니다.Only one switch section in a switch statement executes. C#은 한 switch 섹션에서 다음 switch 섹션으로 계속 실행하도록 허용하지 않습니다.C# doesn't allow execution to continue from one switch section to the next. 이로 인해 다음 코드는 다음과 같은 컴파일러 오류를 생성합니다. CS0163: "한 case 레이블(<case label>)에서 다른 case 레이블로 제어를 이동할 수 없습니다."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;
}

이 요구 사항은 일반적으로 break, goto 또는 return 문을 통해 switch 섹션을 명시적으로 종료하여 충족됩니다.This requirement is usually met by explicitly exiting the switch section by using a break, goto, or return statement. 그러나 다음 코드는 프로그램 제어가 default switch 섹션으로 이동할 수 없도록 하기 때문에 유효합니다.However, the following code is also valid, because it ensures that program control can't 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;                 
}  

case 레이블이 일치 식과 일치하는 switch 섹션에서 문 목록의 실행은 첫 번째 문으로 시작하고 일반적으로 break, goto case, goto label, return 또는 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. 이 경우 switch 문 외부 또는 다른 case 레이블로 제어를 보냅니다.At that point, control is transferred outside the switch statement or to another case label. 사용되는 경우 goto 문은 constant 레이블에 컨트롤을 전달해야 합니다.A goto statement, if it's used, must transfer control to a constant label. 이 제한 사항이 필요합니다. constant가 아닌 레이블에 컨트롤을 전달하려고 하면 코드의 의도치 않은 위치에 컨트롤을 전달하거나 무한 루프를 만드는 것과 같은 원치 않는 부작용이 발생할 수 있기 때문입니다.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 레이블Case labels

각 case 레이블은 일치 식과 비교할 패턴(이전 예제의 caseSwitch 변수)을 지정합니다.Each case label specifies a pattern to compare to the match expression (the caseSwitch variable in the previous examples). 일치하는 경우 제어가 일치하는 첫 번째 case 레이블을 포함하는 switch 섹션으로 전송됩니다.If they match, control is transferred to the switch section that contains the first matching case label. 일치 식과 일치하는 case 레이블 패턴이 없는 경우 제어가 default case 레이블을 포함하는 섹션으로 전송됩니다(있는 경우).If no case label pattern matches the match expression, control is transferred to the section with the default case label, if there's one. default case가 없는 경우 switch 섹션의 문이 실행되지 않으며, 제어가 switch 문 외부로 전송됩니다.If there's no default case, no statements in any switch section are executed, and control is transferred outside the switch statement.

switch 문과 패턴 일치에 대한 자세한 내용은 switch 문을 사용한 패턴 일치 섹션을 참조하세요.For information on the switch statement and pattern matching, see the Pattern matching with the switch statement section.

C# 6에서 상수 패턴만 지원하고 상수 값의 반복을 허용하지 않는 경우 case 레이블은 상호 배타적인 값을 정의하며 하나의 패턴만 일치 식과 일치할 수 있습니다.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. 따라서 case 문이 표시되는 순서는 중요하지 않습니다.As a result, the order in which case statements appear is unimportant.

그러나 C# 7.0에서는 다른 패턴도 지원되므로 case 레이블에서 상호 배타적인 값을 정의할 필요가 없으며 여러 패턴이 일치 식과 일치할 수 있습니다.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. 일치 패턴을 포함하는 첫 번째 switch 섹션의 문만 실행되기 때문에 이제 case 문이 나타나는 순서가 중요합니다.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. C#에서 case 문이 이전 문과 같거나 이전 문의 하위 집합인 switch 섹션을 검색할 경우 컴파일러 오류, CS8120, "Switch case가 이전 case에서 이미 처리되었습니다."를 생성합니다.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."

다음 예제에서는 상호 배타적이 아닌 다양한 패턴을 사용하는 switch 문을 보여 줍니다.The following example illustrates a switch statement that uses a variety of non-mutually exclusive patterns. 더 이상 switch 문의 첫 번째 섹션이 아니도록 case 0: switch 섹션을 이동하는 경우 해당 값이 0인 정수는 case int val 문에 정의된 패턴인 모든 정수의 하위 집합이므로 C#에서 컴파일러 오류를 생성합니다.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>();
   }
}

이 문제를 해결하고 다음 두 가지 방법 중 하나로 컴파일러 경고를 제거할 수 있습니다.You can correct this issue and eliminate the compiler warning in one of two ways:

  • switch 섹션의 순서 변경By changing the order of the switch sections.

  • case 레이블에서 when 절 사용By using a when clause in the case label.

default caseThe default case

default case는 일치 식이 다른 case 레이블과 일치하지 않는 경우 실행할 switch 섹션을 지정합니다.The default case specifies the switch section to execute if the match expression doesn't match any other case label. default case가 없고 일치 식이 다른 case 레이블과 일치하지 않는 경우 프로그램 흐름이 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.

default case는 switch 문에 임의 순서로 표시될 수 있습니다.The default case can appear in any order in the switch statement. 소스 코드에서 해당 순서와 관계없이 항상 모든 case 레이블이 평가된 후 마지막에 평가됩니다.Regardless of its order in the source code, it's always evaluated last, after all case labels have been evaluated.

switch 문을 사용한 패턴 일치 Pattern matching with the switch statement

case 문은 일치 식과 일치할 경우 포함하는 switch 섹션이 실행되는 패턴을 정의합니다.Each case statement defines a pattern that, if it matches the match expression, causes its containing switch section to be executed. 상수 패턴은 모든 버전의 C#에서 지원됩니다.All versions of C# support the constant pattern. 나머지 패턴은 C# 7.0부터 지원됩니다.The remaining patterns are supported beginning with C# 7.0.

상수 패턴Constant pattern

상수 패턴은 일치 식이 지정된 상수와 같은지 여부를 테스트합니다.The constant pattern tests whether the match expression equals a specified constant. 사용되는 구문은 다음과 같습니다.Its syntax is:

   case constant:

여기서 constant는 테스트할 값입니다.where constant is the value to test for. constant는 다음 상수 식 중 하나가 될 수 있습니다.constant can be any of the following constant expressions:

  • bool 리터럴(true 또는 false)A bool literal, either true or false.
  • int, long 또는 byte와 같은 모든 정수 계열 상수Any integral constant, such as an int, a long, or a byte.
  • 선언된 const 변수의 이름The name of a declared const variable.
  • 열거형 상수An enumeration constant.
  • char 리터럴A char literal.
  • string 리터럴A string literal.

상수 식은 다음과 같이 계산됩니다.The constant expression is evaluated as follows:

  • exprconstant가 정수 형식인 경우 C# 같음 연산자는 식에서 true를 반환하는지 여부 즉, expr == constant인지 여부를 확인합니다.If expr and constant are integral types, the C# equality operator determines whether the expression returns true (that is, whether expr == constant).

  • 정수 형식이 아니면 static Object.Equals(expr, constant) 메서드 호출을 통해 식의 값이 결정됩니다.Otherwise, the value of the expression is determined by a call to the static Object.Equals(expr, constant) method.

다음 예제에서는 상수 패턴을 사용하여 특정 날짜가 주말인지, 작업 주의 첫째 날인지, 작업 주의 마지막 날인지 또는 작업 주의 중간인지를 확인합니다.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. 현재 날짜의 DateTime.DayOfWeek 속성을 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.

다음 예제에서는 상수 패턴을 사용하여 자동 커피 머신을 시뮬레이트하는 콘솔 애플리케이션의 사용자 입력을 처리합니다.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.


형식 패턴Type pattern

형식 패턴은 간결한 형식 평가 및 변환을 사용하도록 설정합니다.The type pattern enables concise type evaluation and conversion. switch 문과 함께 사용하여 패턴 일치를 수행하는 경우 식을 지정된 형식으로 변환할 수 있는지 여부를 테스트하고, 변환할 수 있으면 해당 형식의 변수로 캐스팅합니다.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. 사용되는 구문은 다음과 같습니다.Its syntax is:

   case type varname

여기서 typeexpr의 결과가 변환되는 형식의 이름이고, varname은 일치에 성공할 경우 expr의 결과가 변환되는 개체입니다.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. expr의 컴파일 시간 형식은 C# 7.1부터 제네릭 형식 매개 변수일 수 있습니다.The compile-time type of expr may be a generic type parameter, starting with C# 7.1.

다음 중 하나가 true일 경우 case 식은 true입니다.The case expression is true if any of the following is true:

  • exprtype과 동일한 형식의 인스턴스입니다.expr is an instance of the same type as type.

  • exprtype에서 파생된 형식의 인스턴스입니다.expr is an instance of a type that derives from type. 즉, expr의 결과를 type의 인스턴스로 업캐스트할 수 있습니다.In other words, the result of expr can be upcast to an instance of type.

  • expr의 컴파일 시간 형식은 type의 기본 클래스이고 expr의 런타임 형식은 type이거나 type에서 파생됩니다.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. 변수의 컴파일 시간 형식은 해당 형식 선언에 정의된 변수의 형식입니다.The compile-time type of a variable is the variable's type as defined in its type declaration. 변수의 런타임 형식은 해당 변수에 할당된 인스턴스의 형식입니다.The runtime type of a variable is the type of the instance that is assigned to that variable.

  • exprtype 인터페이스를 구현하는 형식의 인스턴스입니다.expr is an instance of a type that implements the type interface.

case 식이 true이면 varname이 한정적으로 할당되고 switch 섹션 내의 로컬 범위만 갖습니다.If the case expression is true, varname is definitely assigned and has local scope within the switch section only.

null은 형식과 일치하지 않습니다.Note that null doesn't match a type. null과 일치하려면 다음 case 레이블을 사용합니다.To match a null, you use the following case label:

case null:

다음 예제에서는 형식 패턴을 사용하여 다양한 종류의 컬렉션 형식에 대한 정보를 제공합니다.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

object 대신, 다음 코드와 같이 컬렉션 형식을 형식 매개 변수로 사용하여 제네릭 메서드를 만들 수 있습니다.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.

제네릭 버전은 두 가지 측면에서 첫 번째 샘플과 다릅니다.The generic version is different than the first sample in two ways. 먼저 null case를 사용할 수 없습니다.First, you can't use the null case. 컴파일러가 임의 형식 Tobject 이외의 형식으로 변환할 수 없으므로 constant case를 사용할 수 없습니다.You can't use any constant case because the compiler can't convert any arbitrary type T to any type other than object. default case였던 항목이 이제 Null이 아닌 object에 대해 테스트됩니다.What had been the default case now tests for a non-null object. 즉, default case는 null에 대해서만 테스트됩니다.That means the default case tests only for null.

패턴 일치를 사용하지 않을 경우 이 코드를 다음과 같이 작성할 수 있습니다.Without pattern matching, this code might be written as follows. 형식 패턴 일치를 사용하면 변환 결과가 null인지 여부를 테스트하거나 반복된 캐스트를 수행할 필요가 없으므로 더욱 단순하고 읽기 쉬운 코드가 생성됩니다.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

case 문 및 when The case statement and the when clause

C# 7.0부터 case 문이 상호 배타적일 필요가 없으므로 when 절을 추가하여 case 문이 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. when 절은 부울 값을 반환하는 모든 식일 수 있습니다.The when clause can be any expression that returns a Boolean value.

다음 예제에서는 기본 Shape 클래스, Shape에서 파생된 Rectangle 클래스 및 Rectangle에서 파생된 Square 클래스를 정의합니다.The following example defines a base Shape class, a Rectangle class that derives from Shape, and a Square class that derives from Rectangle. when 절을 사용하여 ShowShapeInfo에서 Square 개체로 인스턴스화되지 않은 경우에도 동일한 길이 및 너비가 할당된 Rectangle 개체를 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. 이 메서드는 null인 개체나 면적이 0인 도형에 대한 정보를 표시하지 않습니다.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

Shape 개체가 null인지 여부를 테스트하는 예제의 when 절은 실행되지 않습니다.Note that the when clause in the example that attempts to test whether a Shape object is null doesn't execute. null인지 테스트하는 올바른 형식 패턴은 case null:입니다.The correct type pattern to test for a null is case null:.

C# 언어 사양C# language specification

자세한 내용은 C# 언어 사양switch 문을 참조하세요.For more information, see The switch statement in the C# Language Specification. 언어 사양은 C# 구문 및 사용법에 대 한 신뢰할 수 있는 소스 됩니다.The language specification is the definitive source for C# syntax and usage.

참고 항목See also