패턴 일치 - 패턴의 isswitch 식, 연산자 and, ornot

isexpression, switch 문switch 식을 사용하여 입력 식을 여러 특성과 일치시킬 수 있습니다. C#은 선언, 형식, 상수, 관계형, 속성, 목록, var 및 무시 항목을 비롯한 여러 패턴을 지원합니다. 패턴은 부울 논리 키워드 and, ornot을(를) 사용하여 결합할 수 있습니다.

다음 C# 식과 문은 패턴 일치를 지원합니다.

해당 구문에서 다음 패턴 중 하나에 대해 입력 식을 매칭할 수 있습니다.

  • 선언 패턴: 식의 런타임 형식을 확인하고 일치가 성공하면 식 결과를 선언된 변수에 할당합니다.
  • 형식 패턴: 식의 런타임 형식을 확인합니다.
  • 상수 패턴: 식 결과가 지정된 상수와 같은지 테스트합니다.
  • 관계형 패턴: 식 결과를 지정된 상수와 비교합니다.
  • 논리 패턴: 식이 패턴의 논리적 조합과 일치하는지 테스트합니다.
  • 속성 패턴: 식의 속성 또는 필드가 중첩 패턴과 일치하는지 테스트합니다.
  • 위치 패턴: 식 결과를 분해하고 결과 값이 중첩 패턴과 일치하는지 테스트합니다.
  • var 패턴: 모든 식을 매칭하고 결과를 선언된 변수에 할당합니다.
  • 무시 패턴: 모든 식을 매칭합니다.
  • 목록 패턴: 시퀀스 요소가 해당 중첩 패턴과 일치하는지 테스트합니다. C# 11에 도입됨.

논리, 속성, 위치목록 패턴은 재귀 패턴입니다. 즉, 중첩 패턴을 포함할 수 있습니다.

이러한 패턴을 사용하여 데이터 기반 알고리즘을 빌드하는 방법에 대한 예제는 자습서: 패턴 일치를 사용하여 형식 기반 및 데이터 기반 알고리즘 빌드를 참조하세요.

선언 및 형식 패턴

식의 런타임 형식이 지정된 형식과 호환되는지 확인하기 위해 선언 및 형식 패턴을 사용합니다. 선언 패턴을 사용하면 새 지역 변수를 선언할 수도 있습니다. 선언 패턴이 식과 일치하는 경우 다음 예제와 같이 해당 변수에 변환된 식 결과가 할당됩니다.

object greeting = "Hello, World!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: hello, world!
}

T 형식의 선언 패턴은 식 결과가 null이 아니고 다음 조건 중 하나라도 참일 때 식과 일치합니다.

  • 식 결과의 런타임 형식은 T입니다.

  • 식 결과의 런타임 형식은 T 형식에서 파생되거나 인터페이스 T를 구현합니다. 또는 여기에서 T로 또 다른 암시적 참조 변환이 존재합니다. 다음 예제에서는 이 조건이 참인 경우의 두 가지 사례를 보여 줍니다.

    var numbers = new int[] { 10, 20, 30 };
    Console.WriteLine(GetSourceLabel(numbers));  // output: 1
    
    var letters = new List<char> { 'a', 'b', 'c', 'd' };
    Console.WriteLine(GetSourceLabel(letters));  // output: 2
    
    static int GetSourceLabel<T>(IEnumerable<T> source) => source switch
    {
        Array array => 1,
        ICollection<T> collection => 2,
        _ => 3,
    };
    

    앞의 예제에서 GetSourceLabel 메서드를 처음 호출할 때 인수의 런타임 형식 int[]Array 형식에서 파생되기 때문에 첫 번째 패턴은 인수 값과 일치합니다. GetSourceLabel 메서드에 대한 두 번째 호출에서 인수의 런타임 형식 List<T>Array 형식에서 파생되지 않지만 ICollection<T> 인터페이스를 구현합니다.

  • 식 결과의 런타임 형식은 기본 형식 T를 사용하는 null 허용 값 형식입니다.

  • 식 결과의 런타임 형식에서 T 형식으로 boxing 또는 unboxing 변환이 존재합니다.

다음 예제에서는 마지막 두 조건을 보여 줍니다.

int? xNullable = 7;
int y = 23;
object yBoxed = y;
if (xNullable is int a && yBoxed is int b)
{
    Console.WriteLine(a + b);  // output: 30
}

식의 형식만 확인하려는 경우 다음 예제와 같이 변수의 이름을 대신하여 무시 _을 사용할 수 있습니다.

public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}

public static class TollCalculator
{
    public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
    {
        Car _ => 2.00m,
        Truck _ => 7.50m,
        null => throw new ArgumentNullException(nameof(vehicle)),
        _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
    };
}

이 목적을 위해 다음 예제와 같이 형식 패턴을 사용할 수 있습니다.

public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    Car => 2.00m,
    Truck => 7.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};

선언 패턴과 마찬가지로, 식 결과가 null이 아니고 해당 런타임 형식이 위에 나열된 조건 중 하나를 충족하는 경우 형식 패턴이 식과 일치합니다.

null이 아닌지 확인하려면 다음 예제와 같이 부정null상수 패턴을 사용할 수 있습니다.

if (input is not null)
{
    // ...
}

자세한 내용은 기능 제안 노트의 선언 패턴형식 패턴 섹션을 참조하세요.

상수 패턴

다음 예제와 같이 식 결과가 지정된 상수와 같은지 테스트하려면 상수 패턴을 사용합니다.

public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
    1 => 12.0m,
    2 => 20.0m,
    3 => 27.0m,
    4 => 32.0m,
    0 => 0.0m,
    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};

상수 패턴에서 다음과 같은 상수 식을 사용할 수 있습니다.

식은 상수 형식으로 변환할 수 있는 형식이어야 하며, 형식이 Span<char> 또는 ReadOnlySpan<char>인 식은 C# 11 이상 버전의 상수 문자열과 일치시킬 수 있습니다.

다음 예제와 같이 null을 확인하려면 상수 패턴을 사용합니다.

if (input is null)
{
    return;
}

컴파일러는 x is null 식이 평가될 때 사용자 오버로드된 같음 연산자 ==가 호출되지 않도록 보장합니다.

다음 예제와 같이 null이 아님을 확인하려면 부정null 상수 패턴을 사용할 수 있습니다.

if (input is not null)
{
    // ...
}

자세한 내용은 기능 제안 노트의 상수 패턴 섹션을 참조하세요.

관계형 패턴

다음 예제와 같이 식 결과를 상수와 비교하려면 관계형 패턴을 사용합니다.

Console.WriteLine(Classify(13));  // output: Too high
Console.WriteLine(Classify(double.NaN));  // output: Unknown
Console.WriteLine(Classify(2.4));  // output: Acceptable

static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};

관계형 패턴에서는 관계 연산자<, >, <= 또는 >= 중 하나를 사용할 수 있습니다. 관계형 패턴의 오른쪽 부분은 상수 식이어야 합니다. 상수 식은 정수, 부동 소수점, char 또는 enum 형식일 수 있습니다.

식 결과가 특정 범위에 있는지 확인하려면 다음 예제와 같이 결합 and 패턴을 기준으로 매칭합니다.

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 3, 14)));  // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 7, 19)));  // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 2, 17)));  // output: winter

static string GetCalendarSeason(DateTime date) => date.Month switch
{
    >= 3 and < 6 => "spring",
    >= 6 and < 9 => "summer",
    >= 9 and < 12 => "autumn",
    12 or (>= 1 and < 3) => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};

식 결과가 null인 경우 또는 nullable 또는 unboxing 변환을 통해 상수 형식으로 변환하지 못하는 경우 관계형 패턴이 식과 일치하지 않습니다.

자세한 내용은 기능 제안 노트의 관계형 패턴 섹션을 참조하세요.

논리 패턴

not, and, or 패턴 조합기를 사용하여 다음과 같은 논리 패턴을 만듭니다.

  • 부정not 패턴은 부정 패턴이 식과 일치하지 않는 경우 식과 일치하는 패턴입니다. 다음 예에서는 식이 null이 아닌지 확인하기 위해 상수null 패턴을 부정할 수 있는 방법을 보여 줍니다.

    if (input is not null)
    {
        // ...
    }
    
  • 결합and 패턴은 두 패턴이 모두 식과 일치하는 경우 식과 일치하는 패턴입니다. 다음 예제에서는 관계형 패턴을 결합하여 값이 특정 범위에 있는지 확인하는 방법을 보여 줍니다.

    Console.WriteLine(Classify(13));  // output: High
    Console.WriteLine(Classify(-100));  // output: Too low
    Console.WriteLine(Classify(5.7));  // output: Acceptable
    
    static string Classify(double measurement) => measurement switch
    {
        < -40.0 => "Too low",
        >= -40.0 and < 0 => "Low",
        >= 0 and < 10.0 => "Acceptable",
        >= 10.0 and < 20.0 => "High",
        >= 20.0 => "Too high",
        double.NaN => "Unknown",
    };
    
  • 분리or 패턴: 다음 예제와 같이 패턴 중 하나가 식과 일치하는 경우 식과 일치하는 패턴입니다.

    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring
    
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        3 or 4 or 5 => "spring",
        6 or 7 or 8 => "summer",
        9 or 10 or 11 => "autumn",
        12 or 1 or 2 => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
    

앞의 예제에서 볼 수 있듯이 패턴에서 조합기 패턴을 반복적으로 사용할 수 있습니다.

확인 우선 순위 및 순서

패턴 결합자는 다음과 같이 가장 높은 우선 순위에서 가장 낮은 순서로 정렬됩니다.

  • not
  • and
  • or

논리 패턴이 is 식의 패턴인 경우 논리 패턴 결합자의 우선 순위는 논리 연산자(비트 논리 연산자와 부울 논리 연산자 모두)의 우선 순위보다 높습니다. 그렇지 않으면 논리 패턴 결합자의 우선 순위가 논리 및 조건부 논리 연산자의 우선 순위보다 낮습니다. 우선 순위 수준에 따라 정렬된 전체 연산자 목록은 C# 연산자 문서의 연산자 우선 순위 섹션을 참조하세요.

우선 순위를 명시적으로 지정하려면 다음 예제와 같이 괄호를 사용합니다.

static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');

참고 항목

패턴을 확인하는 순서는 정의되지 않습니다. 런타임에 orand 패턴의 오른쪽 중첩 패턴을 먼저 확인할 수 있습니다.

자세한 내용은 기능 제안 노트의 패턴 조합기 섹션을 참조하세요.

속성 패턴

다음 예제와 같이 중첩 패턴에 대해 식의 속성 또는 필드를 매칭하려면 속성 패턴을 사용합니다.

static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };

식 결과가 null이 아니고 모든 중첩 패턴이 식 결과의 해당 속성 또는 필드와 일치하는 경우 속성 패턴은 식과 일치합니다.

다음 예제와 같이 런타임 형식 검사 및 변수 선언을 속성 패턴에 추가할 수도 있습니다.

Console.WriteLine(TakeFive("Hello, world!"));  // output: Hello
Console.WriteLine(TakeFive("Hi!"));  // output: Hi!
Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' }));  // output: 12345
Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' }));  // output: abc

static string TakeFive(object input) => input switch
{
    string { Length: >= 5 } s => s.Substring(0, 5),
    string s => s,

    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
    ICollection<char> symbols => new string(symbols.ToArray()),

    null => throw new ArgumentNullException(nameof(input)),
    _ => throw new ArgumentException("Not supported input type."),
};

속성 패턴은 재귀 패턴입니다. 즉, 모든 패턴을 중첩 패턴으로 사용할 수 있습니다. 다음 예제와 같이 중첩 패턴에 대해 데이터의 일부를 매칭하려면 속성 패턴을 사용합니다.

public record Point(int X, int Y);
public record Segment(Point Start, Point End);

static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start: { Y: 0 } } or { End: { Y: 0 } };

앞의 예제에서는 or패턴 조합기레코드 형식을 사용합니다.

C# 10부터 속성 패턴 내에서 중첩된 속성 또는 필드를 참조할 수 있습니다. 이 기능을 확장 속성 패턴이라고 합니다. 예를 들어 이전 예제의 메서드를 다음과 동일한 코드로 리팩터링할 수 있습니다.

static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };

자세한 내용은 기능 제안 메모의 속성 패턴 섹션과 확장 속성 패턴 기능 제안 노트를 참조하세요.

IDE0170(속성 패턴 단순화) 스타일 규칙을 사용하여 확장 속성 패턴을 사용할 장소를 제안하여 코드 가독성을 향상시킬 수 있습니다.

위치 패턴

다음 예제와 같이 식 결과를 분해하고 해당 중첩 패턴에 대해 결과 값을 매칭하려면 위치 패턴을 사용합니다.

public readonly struct Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) => (X, Y) = (x, y);

    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}

static string Classify(Point point) => point switch
{
    (0, 0) => "Origin",
    (1, 0) => "positive X basis end",
    (0, 1) => "positive Y basis end",
    _ => "Just a point",
};

앞의 예제에서 식의 형식은 식 결과를 분해하는 데 사용되는 분해 메서드를 포함합니다. 위치 패턴에 대해 튜플 형식의 식을 매칭할 수도 있습니다. 이 방식으로 다음 예제와 같이 다양한 패턴에 대해 여러 입력을 매칭할 수 있습니다.

static decimal GetGroupTicketPriceDiscount(int groupSize, DateTime visitDate)
    => (groupSize, visitDate.DayOfWeek) switch
    {
        (<= 0, _) => throw new ArgumentException("Group size must be positive."),
        (_, DayOfWeek.Saturday or DayOfWeek.Sunday) => 0.0m,
        (>= 5 and < 10, DayOfWeek.Monday) => 20.0m,
        (>= 10, DayOfWeek.Monday) => 30.0m,
        (>= 5 and < 10, _) => 12.0m,
        (>= 10, _) => 15.0m,
        _ => 0.0m,
    };

앞의 예제에서는 관계형논리형 패턴을 사용합니다.

다음 예제와 같이 위치 패턴에서 튜플 요소 및 Deconstruct 매개 변수의 이름을 사용할 수 있습니다.

var numbers = new List<int> { 1, 2, 3 };
if (SumAndCount(numbers) is (Sum: var sum, Count: > 0))
{
    Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}");  // output: Sum of [1 2 3] is 6
}

static (double Sum, int Count) SumAndCount(IEnumerable<int> numbers)
{
    int sum = 0;
    int count = 0;
    foreach (int number in numbers)
    {
        sum += number;
        count++;
    }
    return (sum, count);
}

다음 방법 중 하나로 위치 패턴을 확장할 수도 있습니다.

  • 다음 예제와 같이 런타임 형식 검사 및 변수 선언을 추가합니다.

    public record Point2D(int X, int Y);
    public record Point3D(int X, int Y, int Z);
    
    static string PrintIfAllCoordinatesArePositive(object point) => point switch
    {
        Point2D (> 0, > 0) p => p.ToString(),
        Point3D (> 0, > 0, > 0) p => p.ToString(),
        _ => string.Empty,
    };
    

    앞의 예제에서는 Deconstruct 메서드를 암시적으로 제공하는 위치 레코드를 사용합니다.

  • 다음 예제와 같이 위치 패턴 내에서 속성 패턴을 사용합니다.

    public record WeightedPoint(int X, int Y)
    {
        public double Weight { get; set; }
    }
    
    static bool IsInDomain(WeightedPoint point) => point is (>= 0, >= 0) { Weight: >= 0.0 };
    
  • 다음 예제와 같이 앞에 나온 두 가지 사용을 결합합니다.

    if (input is WeightedPoint (> 0, > 0) { Weight: > 0.0 } p)
    {
        // ..
    }
    

위치 패턴은 재귀 패턴입니다. 즉, 모든 패턴을 중첩 패턴으로 사용할 수 있습니다.

자세한 내용은 기능 제안 노트의 위치 패턴 섹션을 참조하세요.

var 패턴

다음 예제와 같이 null을 포함한 모든 식을 매칭하고 그 결과를 새 지역 변수에 할당하려면 var 패턴을 사용합니다.

static bool IsAcceptable(int id, int absLimit) =>
    SimulateDataFetch(id) is var results 
    && results.Min() >= -absLimit 
    && results.Max() <= absLimit;

static int[] SimulateDataFetch(int id)
{
    var rand = new Random();
    return Enumerable
               .Range(start: 0, count: 5)
               .Select(s => rand.Next(minValue: -10, maxValue: 11))
               .ToArray();
}

var 패턴은 부울 식 내에서 중간 계산 결과를 저장하기 위해 임시 변수가 필요한 경우 유용합니다. 다음 예제와 같이 switch 식 또는 문의 when 케이스 가드에서 추가 검사를 수행해야 하는 경우에도 var 패턴을 사용할 수 있습니다.

public record Point(int X, int Y);

static Point Transform(Point point) => point switch
{
    var (x, y) when x < y => new Point(-x, y),
    var (x, y) when x > y => new Point(x, -y),
    var (x, y) => new Point(x, y),
};

static void TestTransform()
{
    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }
    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }
}

앞의 예제에서 var (x, y) 패턴은 위치 패턴(var x, var y)과 동일합니다.

var 패턴에서 선언된 변수의 형식은 패턴에 대해 일치하는 식의 컴파일 시간 형식입니다.

자세한 내용은 기능 제안 노트의 변수 패턴 섹션을 참조하세요.

무시 패턴

다음 예제와 같이 null을 포함한 모든 식을 매칭하려면 무시 패턴_을 사용합니다.

Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0
Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0

static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
    DayOfWeek.Monday => 0.5m,
    DayOfWeek.Tuesday => 12.5m,
    DayOfWeek.Wednesday => 7.5m,
    DayOfWeek.Thursday => 12.5m,
    DayOfWeek.Friday => 5.0m,
    DayOfWeek.Saturday => 2.5m,
    DayOfWeek.Sunday => 2.0m,
    _ => 0.0m,
};

앞의 예제에서 무시 패턴은 null을 처리하는 데 사용되고 DayOfWeek 열거형의 해당 멤버가 없는 정수 값을 사용합니다. 이렇게 하면 예제의 switch 식이 가능한 모든 입력 값을 처리할 수 있습니다. 식에서 무시 패턴을 사용하지 않으며 식의 패턴 중 입력과 일치하는 것이 없는 경우 런타임은 switch예외를 throw합니다. switch 식이 가능한 모든 입력 값을 처리하지 않는 경우 컴파일러에서 경고를 생성합니다.

무시 패턴은 is 식 또는 switch 문의 패턴이 될 수 없습니다. 이 경우 모든 식과 매칭하려면 무시와 함께 var 패턴을 사용합니다(var _). 무시 패턴은 switch 식의 패턴일 수 있습니다.

자세한 내용은 기능 제안 노트의 무시 패턴 섹션을 참조하세요.

괄호로 묶인 패턴

모든 패턴 주위에 괄호를 넣을 수 있습니다. 일반적으로 다음 예제와 같이 논리 패턴에서 우선 순위를 강조 표시하거나 변경하기 위해 괄호를 사용합니다.

if (input is not (float or double))
{
    return;
}

목록 패턴

C# 11부터는 다음 예제와 같이 배열 또는 목록을 패턴의 시퀀스와 일치시킬 수 있습니다.

int[] numbers = { 1, 2, 3 };

Console.WriteLine(numbers is [1, 2, 3]);  // True
Console.WriteLine(numbers is [1, 2, 4]);  // False
Console.WriteLine(numbers is [1, 2, 3, 4]);  // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]);  // True

앞의 예제와 같이 목록 패턴은 각 중첩 패턴이 입력 시퀀스의 해당 요소와 일치할 때 일치합니다. 목록 패턴 내에서 모든 패턴을 사용할 수 있습니다. 요소를 일치시키려면 무시 항목 패턴을 사용하거나, 요소를 캡처하려는 경우 다음 예제와 같이 var 패턴을 사용합니다.

List<int> numbers = new() { 1, 2, 3 };

if (numbers is [var first, _, _])
{
    Console.WriteLine($"The first element of a three-item list is {first}.");
}
// Output:
// The first element of a three-item list is 1.

앞의 예제는 전체 입력 시퀀스를 목록 패턴과 일치합니다. 입력 시퀀스의 시작 및/및 끝 부분에서만 요소를 일치시키려면 다음 예제와 같이 슬라이스 패턴..을 사용합니다.

Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]);  // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]);  // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]);  // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]);  // False

Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]);  // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]);  // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]);  // True

Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]);  // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]);  // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]);  // False

조각 패턴은 0개 이상의 요소와 일치합니다. 목록 패턴에서 최대 하나의 조각 패턴을 사용할 수 있습니다. 조각 패턴은 목록 패턴에만 표시할 수 있습니다.

다음 예제와 같이 조각 패턴 내에 하위 페이턴을 중첩할 수도 있습니다.

void MatchMessage(string message)
{
    var result = message is ['a' or 'A', .. var s, 'a' or 'A']
        ? $"Message {message} matches; inner part is {s}."
        : $"Message {message} doesn't match.";
    Console.WriteLine(result);
}

MatchMessage("aBBA");  // output: Message aBBA matches; inner part is BB.
MatchMessage("apron");  // output: Message apron doesn't match.

void Validate(int[] numbers)
{
    var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
    Console.WriteLine(result);
}

Validate(new[] { -1, 0, 1 });  // output: not valid
Validate(new[] { -1, 0, 0, 1 });  // output: valid

자세한 내용은 목록 패턴 기능 제안 노트를 참조하세요.

C# 언어 사양

자세한 내용은 C# 언어 사양패턴 및 패턴 일치 섹션을 참조하세요.

C# 8 이상에 추가된 기능에 대한 자세한 내용은 다음 기능 제안 노트를 참조하세요.

참고 항목