다음을 통해 공유


패턴과 데이터 일치

이 자습서에서는 패턴 일치를 사용하여 C#에서 데이터를 검사하는 방법을 설명합니다. 소량의 코드를 작성한 다음, 해당 코드를 컴파일하고 실행합니다. 이 자습서에는 C#에서 다양한 종류의 형식을 탐색하는 일련의 단원이 포함되어 있습니다. 이러한 단원에서는 C# 언어의 기본 사항을 설명합니다.

팁 (조언)

코드 조각 블록에 "실행" 단추가 포함된 경우 해당 단추는 대화형 창을 열거나 대화형 창의 기존 코드를 바꿉니다. 코드 조각에 "실행" 단추가 포함되지 않은 경우 코드를 복사하여 현재 대화형 창에 추가할 수 있습니다.

** 이전 자습서에서는 기본 제공 형식과 사용자가 튜플 또는 레코드로 정의하는 형식을 보여주었습니다. 이러한 형식의 인스턴스는 패턴에 대해 검사할 수 있습니다. 인스턴스가 패턴과 일치하는지 여부에 따라 프로그램에서 수행하는 작업이 결정됩니다. 아래 예제에서는 형식 이름 다음에 표시됩니다 ? . 이 기호를 사용하면 이 형식의 값이 null이 될 수 있습니다(예: bool? 일 수 있음truefalse)null 자세한 내용은 Nullable 값 형식을 참조하세요. 패턴을 사용하는 방법을 알아보겠습니다.

값을 일치시키다

이 자습서의 모든 예제에서는 일련의 은행 거래를 나타내는 텍스트 입력을 CSV(쉼표로 구분된 값) 입력으로 사용합니다. 각 샘플에서 is 식 또는 switch 식을 사용하여 레코드를 패턴과 일치시킬 수 있습니다. 첫 번째 예제에서는 , 문자를 기준으로 각 줄을 분할하고, 식 을 사용하여 첫 번째 문자열 필드를 "DEPOSIT" 또는 "WITHDRAWAL" 값과 is. 일치하는 경우 트랜잭션 금액이 현재 계정 잔액에서 추가되거나 공제됩니다. 작동을 확인하려면 "실행" 단추를 누릅니다.

string bankRecords = """
    DEPOSIT,   10000, Initial balance
    DEPOSIT,     500, regular deposit
    WITHDRAWAL, 1000, rent
    DEPOSIT,    2000, freelance payment
    WITHDRAWAL,  300, groceries
    DEPOSIT,     700, gift from friend
    WITHDRAWAL,  150, utility bill
    DEPOSIT,    1200, tax refund
    WITHDRAWAL,  500, car maintenance
    DEPOSIT,     400, cashback reward
    WITHDRAWAL,  250, dining out
    DEPOSIT,    3000, bonus payment
    WITHDRAWAL,  800, loan repayment
    DEPOSIT,     600, stock dividends
    WITHDRAWAL,  100, subscription fee
    DEPOSIT,    1500, side hustle income
    WITHDRAWAL,  200, fuel expenses
    DEPOSIT,     900, refund from store
    WITHDRAWAL,  350, shopping
    DEPOSIT,    2500, project milestone payment
    WITHDRAWAL,  400, entertainment
    """;

double currentBalance = 0.0;
var reader = new StringReader(bankRecords);

string? line;
while ((line = reader.ReadLine()) is not null)
{
    if (string.IsNullOrWhiteSpace(line)) continue;
    // Split the line based on comma delimiter and trim each part
    string[] parts = line.Split(',');

    string? transactionType = parts[0]?.Trim();
    if (double.TryParse(parts[1].Trim(), out double amount))
    {
        // Update the balance based on transaction type
        if (transactionType?.ToUpper() is "DEPOSIT")
            currentBalance += amount;
        else if (transactionType?.ToUpper() is "WITHDRAWAL")
            currentBalance -= amount;

        Console.WriteLine($"{line.Trim()} => Parsed Amount: {amount}, New Balance: {currentBalance}");
    }
}

출력을 검사합니다. 첫 번째 필드의 텍스트 값을 비교하여 각 줄이 처리되는 것을 볼 수 있습니다. 앞의 샘플은 두 값이 같은지 테스트하기 위해 == 연산자를 사용하여 유사하게 생성될 수 있습니다. 변수를 상수와 비교하는 것은 패턴 일치를 위한 기본 구성 요소입니다. 패턴 일치의 일부인 더 많은 구성 요소를 살펴보겠습니다.

열거형 매칭

패턴 매칭의 또 다른 일반적인 용도는 enum 형식의 값과 일치시키는 것입니다. 다음 샘플에서는 입력 레코드를 처리하여 첫 번째 값 이 입금 또는 인출을 기록하는 값인 enum을 만듭니다. 두 번째 값은 트랜잭션의 값입니다. 작동을 확인하려면 "실행" 단추를 누릅니다.

경고

복사하여 붙여넣지 마세요. 다음 샘플을 실행하려면 대화형 창을 다시 설정해야 합니다. 실수를 하면 창이 중단되고 계속하려면 페이지를 새로 고쳐야 합니다.

public static class ExampleProgram
{
    const string bankRecords = """
    DEPOSIT,   10000, Initial balance
    DEPOSIT,     500, regular deposit
    WITHDRAWAL, 1000, rent
    DEPOSIT,    2000, freelance payment
    WITHDRAWAL,  300, groceries
    DEPOSIT,     700, gift from friend
    WITHDRAWAL,  150, utility bill
    DEPOSIT,    1200, tax refund
    WITHDRAWAL,  500, car maintenance
    DEPOSIT,     400, cashback reward
    WITHDRAWAL,  250, dining out
    DEPOSIT,    3000, bonus payment
    WITHDRAWAL,  800, loan repayment
    DEPOSIT,     600, stock dividends
    WITHDRAWAL,  100, subscription fee
    DEPOSIT,    1500, side hustle income
    WITHDRAWAL,  200, fuel expenses
    DEPOSIT,     900, refund from store
    WITHDRAWAL,  350, shopping
    DEPOSIT,    2500, project milestone payment
    WITHDRAWAL,  400, entertainment
    """;

    public static void Main()
    {
        double currentBalance = 0.0;

        foreach (var transaction in TransactionRecords(bankRecords))
        {
            if (transaction.type == TransactionType.Deposit)
                currentBalance += transaction.amount;
            else if (transaction.type == TransactionType.Withdrawal)
                currentBalance -= transaction.amount;
            Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}");
        }
    }

    static IEnumerable<(TransactionType type, double amount)> TransactionRecords(string inputText)
    {
        var reader = new StringReader(inputText);
        string? line;
        while ((line = reader.ReadLine()) is not null)
        {
            string[] parts = line.Split(',');

            string? transactionType = parts[0]?.Trim();
            if (double.TryParse(parts[1].Trim(), out double amount))
            {
                // Update the balance based on transaction type
                if (transactionType?.ToUpper() is "DEPOSIT")
                    yield return (TransactionType.Deposit, amount);
                else if (transactionType?.ToUpper() is "WITHDRAWAL")
                    yield return (TransactionType.Withdrawal, amount);
            }
            else {
            yield return (TransactionType.Invalid, 0.0);
            }
        }
    }
}

public enum TransactionType
{
    Deposit,
    Withdrawal,
    Invalid
}

앞의 예제에서는 if 문을 사용하여 enum 식의 값을 확인합니다. 패턴 일치의 또 다른 형식은 switch 식을 사용합니다. 해당 구문과 이 구문을 사용하는 방법을 살펴보겠습니다.

포괄적인 일치 항목 switch

조건을 테스트할 수 있는 일련의 if 문이 있습니다. 그러나 컴파일러는 일련의 if 문이 완전한지 혹은 이후 if 조건이 이전 조건에 의해 포함되는지 알 수 없습니다. 이 식은 switch 이러한 특성을 모두 충족하도록 보장하여 앱에서 버그를 줄입니다. 시도하고 실험해 봅시다. 다음 코드를 복사합니다. 대화형 창의 두 if 문을 복사한 switch 식으로 교체하십시오. 코드를 수정한 후 대화형 창 맨 위에 있는 "실행" 단추를 눌러 새 샘플을 실행합니다.

currentBalance += transaction switch
{
    (TransactionType.Deposit, var amount) => amount,
    (TransactionType.Withdrawal, var amount) => -amount,
    _ => 0.0,
};

코드를 실행하면 코드가 동일하게 작동하는 것을 볼 수 있습니다. 포섭을 보여 주려면 다음 코드 조각과 같이 스위치 암의 순서를 다시 지정합니다.

currentBalance += transaction switch
{
    (TransactionType.Deposit, var amount) => amount,
    _ => 0.0,
    (TransactionType.Withdrawal, var amount) => -amount,
};

스위치 암의 순서를 다시 지정한 후 "실행" 단추를 누릅니다. 컴파일러는 _와 일치하는 조건이 모든 값에 해당하기 때문에 오류를 보고합니다. 결과적으로, 그 마지막 코드 부분은 TransactionType.Withdrawal 결코 실행되지 않습니다. 컴파일러는 코드에 문제가 있음을 알려줍니다.

컴파일러는 switch 표현식에서 테스트된 식이 어떤 스위치 암과도 일치하지 않는 값을 포함할 수 있는 경우 경고를 발생시킵니다. 일부 값이 조건과 일치하지 않을 수 있는 경우 식이 switch완전하지 않습니다. 또한 입력의 일부 값이 스위치 암과 일치하지 않으면 컴파일러에서 경고를 발생합니다. 예를 들어, _ => 0.0,을(를) 제거하면 잘못된 값이 일치하지 않습니다. 런타임에 오류가 발생할 것입니다. 환경에서 .NET SDK를 설치하고 프로그램을 빌드하면 이 동작을 테스트할 수 있습니다. 온라인 환경에는 출력 창에 경고가 표시되지 않습니다.

형식 패턴

이 자습서를 완료하기 위해 패턴 매칭의 구성 요소 하나를 더 살펴보겠습니다. 형식 패턴입니다. 형식 패턴은 런타임에 식을 테스트하여 지정된 형식인지 확인합니다. is 식 또는 switch 식과 함께 타입 테스트를 사용할 수 있습니다. 두 가지 방법으로 현재 샘플을 수정해 보겠습니다. 먼저 튜플 대신 트랜잭션을 나타내는 형식을 빌드 Deposit 하고 Withdrawal 기록해 보겠습니다. 대화형 창 아래쪽에 다음 선언을 추가합니다.

public record Deposit(double Amount, string description);
public record Withdrawal(double Amount, string description);

다음으로, Main 메서드 뒤에 이 메서드를 추가하여 텍스트를 구문 분석하고 일련의 레코드를 반환합니다.

public static IEnumerable<object?> TransactionRecordType(string inputText)
{
    var reader = new StringReader(inputText);
    string? line;
    while ((line = reader.ReadLine()) is not null)
    {
        string[] parts = line.Split(',');

        string? transactionType = parts[0]?.Trim();
        if (double.TryParse(parts[1].Trim(), out double amount))
        {
            // Update the balance based on transaction type
            if (transactionType?.ToUpper() is "DEPOSIT")
                yield return new Deposit(amount, parts[2]);
            else if (transactionType?.ToUpper() is "WITHDRAWAL")
                yield return new Withdrawal(amount, parts[2]);
        }
        yield return default;
    }
}

마지막으로 메서드의 foreach 루프를 Main 다음 코드로 바꿉다.

foreach (var transaction in TransactionRecordType(bankRecords))
{
    currentBalance += transaction switch
    {
        Deposit d => d.Amount,
        Withdrawal w => -w.Amount,
        _ => 0.0,
    };
    Console.WriteLine($" {transaction} => New Balance: {currentBalance}");
}

그런 다음, "실행" 단추를 눌러 결과를 확인합니다. 이 최종 버전은 형식에 대한 입력을 테스트합니다.

패턴 일치는 식을 특성과 비교하는 어휘를 제공합니다. 패턴에는 식의 형식, 형식 값, 속성 값 및 조합이 포함될 수 있습니다. 식을 패턴과 비교하는 것은 여러 if 비교보다 더 명확할 수 있습니다. 식과 일치하는 데 사용할 수 있는 몇 가지 패턴을 살펴보했습니다. 애플리케이션에서 패턴 일치를 사용하는 방법에는 여러 가지가 있습니다. 먼저 .NET 사이트를 방문하여 .NET SDK를 다운로드하고, 머신에 프로젝트를 만들고, 코딩을 계속합니다. 탐색하는 동안 다음 문서에서 C#에서 패턴 일치에 대해 자세히 알아볼 수 있습니다.