패턴 매칭

  • 9 minutes to read

패턴 매칭(Pattern Matching)은 C#에서 데이터의 구조를 검사하고 특정 패턴과 비교하여 작업을 수행하는 기능입니다. 이는 코드의 가독성과 유지보수성을 높이고, 보다 선언적인 스타일로 프로그래밍할 수 있도록 돕습니다. C# 7.0에서 처음 도입되었으며, 이후 버전에서 더욱 강력한 기능들이 추가되었습니다.

패턴 매칭 개요

패턴 매칭은 is 연산자를 확장하여 특정 데이터의 구조를 검사하는 데 사용됩니다. 이를 통해 데이터 형식을 확인하고, 특정 조건에 따라 분기할 수 있습니다.

다음은 기본적인 패턴 매칭 예제입니다.

> object obj = 123;
> if (obj is int number)
. {
.     Console.WriteLine($"정수: {number}");
. }
정수: 123

위 코드는 objint 형식이면 number 변수에 값을 할당하고 출력합니다.

패턴 매칭을 if 문으로 표현하기

패턴 매칭(pattern matching)을 이용하면 개발자가 패턴과 값이 일치하는지 테스트하고, 일치하면 새로운 변수에 대입하여 사용할 수 있습니다.

다음 예제에서 사용되는 핵심 코드와 의미는 다음과 같습니다.

  • 코드: if (shape is Rectangle r)
  • 의미: 만약, shape 변수의 값이 Rectangle 클래스와 패턴이 맞는다면 Rectangle 형식의 변수 r에 저장

코드: PatternMatchingIf.cs

using System;

namespace PatternMatchingIf
{
    class Shape { }

    class Rectangle : Shape
    {
        public string Name { get; set; } = "사각형";
    }

    class PatternMatchingIf
    {
        static void Main() => ShowShape(new Rectangle());

        static void ShowShape(Shape shape)
        {
            // [1] if 구문을 사용한 패턴 매칭
            if (shape is Rectangle r)
            {
                Console.WriteLine(r.Name);
            }
        }
    }
}
사각형

switch 표현식과 패턴 매칭

C# 8.0부터 switch 문법이 개선되어 패턴 매칭과 함께 더욱 강력한 기능을 제공합니다. 아래 예제에서는 switch 문을 활용한 패턴 매칭의 사용법을 보여줍니다.

switch 문을 사용한 패턴 매칭

다음 코드는 다양한 도형 클래스를 대상으로 switch 문과 패턴 매칭을 활용하여 올바른 정보를 출력하는 예제입니다.

코드: PatternMatchingWithSwitch.cs

using System;
using static System.Console;

class Circle
{
    public int Radius { get; set; } = 10;
}

class Rectangle
{
    public int Length { get; set; }
    public int Height { get; set; }
}

class PatternMatchingWithSwitch
{
    static void Main()
    {
        PrintShape(new Circle()); // 원
        PrintShape(new Rectangle { Length = 20, Height = 10 }); // 직사각형
        PrintShape(new Rectangle { Length = 10, Height = 10 }); // 정사각형
    }

    static void PrintShape(object shape)
    {
        switch (shape)
        {
            case Rectangle s when (s.Length == s.Height):
                WriteLine($"정사각형: {s.Length} x {s.Height}");
                break;
            case Rectangle r:
                WriteLine($"직사각형: {r.Length} x {r.Height}");
                break;
            case Circle c:
                WriteLine($"원: 반지름({c.Radius})");
                break;
            case null:
                throw new ArgumentNullException(nameof(shape));
            default:
                WriteLine("<기타 도형>");
                break;
        }
    }
}
원: 반지름(10)
직사각형: 20 x 10
정사각형: 10 x 10

위 코드에서는 switch 문을 사용하여 개체의 형식을 검사하고, when 절을 활용하여 추가적인 조건을 지정할 수 있습니다.

switch 표현식 사용

C# 8.0에서는 switch 문을 보다 간결하게 사용할 수 있도록 switch 표현식을 도입하였습니다. 아래 예제는 다양한 형식의 입력값을 검사하고, switch 표현식을 활용하여 해당 형식에 맞는 설명을 출력하는 프로그램입니다.

코드: SwitchExpressionDemo.cs

using System;

class SwitchExpressionDemo
{
    static void Main()
    {
        object[] testValues = { 42, 3.14, "Hello", true, null };

        foreach (var obj in testValues)
        {
            string result = GetTypeDescription(obj);
            Console.WriteLine(result);
        }
    }

    static string GetTypeDescription(object obj) => obj switch
    {
        int i => $"정수 {i}",
        double d => $"실수 {d}",
        string s => $"문자열 \"{s}\"",
        bool b => $"불리언 {b}",
        null => "널 값",
        _ => "알 수 없는 형식"
    };
}
정수 42
실수 3.14
문자열 "Hello"
불리언 True
널 값

이처럼 switch 표현식은 코드의 가독성을 높이고 보다 간결한 형태로 패턴 매칭을 활용할 수 있도록 도와줍니다.

튜플 패턴 (Tuple Pattern)

C#에서는 switch 표현식과 튜플을 조합하여 여러 조건을 효과적으로 처리할 수 있습니다. 아래 예제는 특정 좌표 값을 튜플로 표현하고, switch 표현식을 사용하여 위치를 판별하는 프로그램입니다.

코드: TuplePatternDemo.cs

using System;

class TuplePatternDemo
{
    static void Main()
    {
        (int, int) point = (0, 5);
        string position = point switch
        {
            (0, 0) => "원점",
            (0, _) => "Y축 위",
            (_, 0) => "X축 위",
            _ => "일반 위치"
        };

        Console.WriteLine($"({point.Item1}, {point.Item2}) -> {position}");
    }
}
(0, 5) -> Y축 위

이처럼 튜플 패턴을 활용하면 여러 값을 조합하여 switch 표현식에서 직관적으로 패턴 매칭을 수행할 수 있습니다. 이를 통해 코드의 가독성이 높아지고, 복잡한 조건문을 간결하게 표현할 수 있습니다.

리스트 패턴

C# 11.0부터 리스트 패턴이 도입되어 배열과 컬렉션에 대해 패턴 매칭을 보다 직관적으로 수행할 수 있습니다.

코드: ListPatternDemo.cs

using System;
using System.Linq;

class ListPatternDemo
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3 };

        // 리스트 패턴을 활용한 비교
        if (numbers is [1, 2, 3])
        {
            Console.WriteLine("리스트 패턴: 1, 2, 3 배열과 일치");
        }

        // SequenceEqual을 활용한 비교
        if (numbers.SequenceEqual(new int[] { 1, 2, 3 }))
        {
            Console.WriteLine("SequenceEqual: 1, 2, 3 배열과 일치");
        }
    }
}
리스트 패턴: 1, 2, 3 배열과 일치
SequenceEqual: 1, 2, 3 배열과 일치

리스트 패턴을 사용하면 is [1, 2, 3]과 같이 간결하게 배열을 비교할 수 있으며, SequenceEqual을 사용할 때보다 코드가 더 직관적이고 가독성이 향상됩니다.

레코드 형식과 패턴 매칭

C# 9.0에서 도입된 레코드(Record) 형식은 불변(immutable) 데이터를 다룰 때 유용하며, 패턴 매칭과 함께 사용하면 더욱 직관적인 코드를 작성할 수 있습니다. 아래 예제는 record 형식을 정의하고, switch 표현식을 활용하여 특정 조건에 맞는 설명을 반환하는 프로그램입니다.

코드: RecordPatternDemo.cs

using System;

public record Person(string Name, int Age);

class RecordPatternDemo
{
    static void Main()
    {
        Person person = new("홍길동", 21);

        string description = person switch
        {
            { Name: "홍길동", Age: 21 } => "홍길동은(는) 21세입니다.",
            { Age: > 18 } => "성인입니다.",
            _ => "미성년자입니다."
        };

        Console.WriteLine(description);
    }
}
홍길동은(는) 21세입니다.

이처럼 레코드 형식과 패턴 매칭을 함께 사용하면 개체의 특정 필드를 손쉽게 비교할 수 있습니다. 이를 통해 보다 가독성 높은 코드 작성이 가능하며, 복잡한 조건문을 줄일 수 있습니다.

장 요약

C#의 패턴 매칭은 코드를 더 간결하고 직관적으로 만들 수 있는 강력한 기능입니다. 다양한 패턴을 조합하여 복잡한 조건을 깔끔하게 처리할 수 있으며, 최신 C# 버전에서 점점 더 발전하고 있습니다. 이를 활용하면 보다 선언적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com