C# Academy · 강의

판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)

태그 열거형과 작은 클래스를 사용해 C# 6에서 판별 합집합을 모델링하고, 팩터리 메서드를 만들며, default에서 예외를 던지는 switch로 변형을 처리합니다.

레슨 3/38개 단계

판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 3개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 3개의 강의가 포함되어 있습니다.

C# 6의 DU 아이디어

목표: C# 6에서 작은 판별된 합집합을 만듭니다.

  • 현재 경우를 나타내는 태그 열거형
  • 데이터를 담는 작은 경우별 클래스
  • 유효한 경우를 생성하는 Factory 메서드
  • 모든 변형을 처리하는 스위치 + 기본값 예외 발생

태그와 팩터리

태그 열거형과 팩터리 메서드를 사용하여 유효한 경우만 구성합니다. 다른 경우에 해당하는 필드는 사용하지 않은 상태로 둡니다.

using System;

public enum PaymentKind { Cash, Card, Wire }

public sealed class Payment
{
  public PaymentKind Kind;

  // per-case data (only one is meaningful per instance)
  public string CardLast4; // for Card
  public string Iban;      // for Wire

  private Payment() { }

  // factories keep invariants
  public static Payment Cash()
  {
    Payment p = new Payment();
    p.Kind = PaymentKind.Cash;
    return p;
  }

  public static Payment Card(string last4)
  {
    if (string.IsNullOrEmpty(last4) || last4.Length != 4)
      throw new ArgumentException("last4 must be 4 digits", "last4");
    Payment p = new Payment();
    p.Kind = PaymentKind.Card;
    p.CardLast4 = last4;
    return p;
  }

  public static Payment Wire(string iban)
  {
    if (string.IsNullOrEmpty(iban))
      throw new ArgumentException("iban must not be empty", "iban");
    Payment p = new Payment();
    p.Kind = PaymentKind.Wire;
    p.Iban = iban;
    return p;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Payment a = Payment.Cash();
    Payment b = Payment.Card("1234");
    Payment c = Payment.Wire("TR00BANKIBAN");
    Console.WriteLine(a.Kind + ", " + b.Kind + ", " + c.Kind);
  }
}

변형 처리

태그에 대한 일반적인 스위치를 사용하면 처리가 명확해집니다. 기본값에서 예외를 발생시키는 처리를 두면 테스트 중 처리되지 않은 변형을 드러낼 수 있습니다.

using System;

public enum PaymentKind { Cash, Card, Wire }

public sealed class Payment
{
  public PaymentKind Kind;
  public string CardLast4;
  public string Iban;

  public static Payment Cash()
  {
    Payment p = new Payment(); p.Kind = PaymentKind.Cash; return p;
  }
  public static Payment Card(string last4)
  {
    if (string.IsNullOrEmpty(last4) || last4.Length != 4) throw new ArgumentException("last4");
    Payment p = new Payment(); p.Kind = PaymentKind.Card; p.CardLast4 = last4; return p;
  }
  public static Payment Wire(string iban)
  {
    if (string.IsNullOrEmpty(iban)) throw new ArgumentException("iban");
    Payment p = new Payment(); p.Kind = PaymentKind.Wire; p.Iban = iban; return p;
  }
}

public static class Exhaustive
{
  public static Exception Unhandled(object x)
  {
    return new InvalidOperationException("Unhandled case: " + x);
  }
}

public class Program
{
  static string Describe(Payment p)
  {
    switch (p.Kind)
    {
      case PaymentKind.Cash: return "Cash";
      case PaymentKind.Card: return "Card ****" + p.CardLast4;
      case PaymentKind.Wire: return "Wire " + p.Iban;
      default: throw Exhaustive.Unhandled(p.Kind);
    }
  }

  public static void Main(string[] args)
  {
    Console.WriteLine(Describe(Payment.Card("9876")));
  }
}

Match 도우미(방문자 패턴과 유사)

작은 Match 도우미가 스위치 처리를 한곳에 모으고 값을 반환하므로, 호출부를 깔끔하게 유지할 수 있습니다.

using System;

public enum PaymentKind { Cash, Card, Wire }

public sealed class Payment
{
  public PaymentKind Kind;
  public string CardLast4;
  public string Iban;

  public static Payment Cash() { Payment p = new Payment(); p.Kind = PaymentKind.Cash; return p; }
  public static Payment Card(string last4) { Payment p = new Payment(); p.Kind = PaymentKind.Card; p.CardLast4 = last4; return p; }
  public static Payment Wire(string iban) { Payment p = new Payment(); p.Kind = PaymentKind.Wire; p.Iban = iban; return p; }
}

public static class PaymentMatch
{
  public static T Match<T>(
    Payment p,
    Func<T> onCash,
    Func<string, T> onCard,
    Func<string, T> onWire)
  {
    switch (p.Kind)
    {
      case PaymentKind.Cash: return onCash();
      case PaymentKind.Card: return onCard(p.CardLast4);
      case PaymentKind.Wire: return onWire(p.Iban);
      default: throw new InvalidOperationException("Unhandled: " + p.Kind);
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Payment p = Payment.Card("1234");
    string summary = PaymentMatch.Match(
      p,
      delegate { return "Cash"; },
      delegate(string last4) { return "Card ****" + last4; },
      delegate(string iban) { return "Wire " + iban; }
    );
    Console.WriteLine(summary);
  }
}

팩터리를 통한 불변식 보장

팩터리는 불변식을 보장합니다. 각 경우는 의미 있는 필드만 초기화하고, 잘못된 입력은 조기에 거부합니다.

using System;

public enum ResultKind { Ok, Error }

public sealed class Result
{
  public ResultKind Kind;
  public string Message; // only for Error
  public int Value;      // only for Ok

  private Result() { }

  public static Result Ok(int value)
  {
    Result r = new Result();
    r.Kind = ResultKind.Ok;
    r.Value = value;
    r.Message = null;
    return r;
  }

  public static Result Error(string message)
  {
    if (string.IsNullOrEmpty(message)) throw new ArgumentException("message");
    Result r = new Result();
    r.Kind = ResultKind.Error;
    r.Message = message;
    r.Value = 0;
    return r;
  }
}

public class Program
{
  static string Show(Result r)
  {
    switch (r.Kind)
    {
      case ResultKind.Ok: return "OK: " + r.Value;
      case ResultKind.Error: return "ERROR: " + r.Message;
      default: throw new InvalidOperationException("Unhandled: " + r.Kind);
    }
  }

  public static void Main(string[] args)
  {
    Console.WriteLine(Show(Result.Ok(5)));
    Console.WriteLine(Show(Result.Error("Boom")));
  }
}

팁과 절충점

팁:

  • 작고 목적이 분명한 경우와 팩터리를 우선 사용합니다.
  • 코드를 DRY하게 유지하도록 한곳의 스위치 도우미에서 변형을 처리합니다.
  • 테스트에서 누락된 경우를 드러내도록 기본값에서 예외를 발생시키는 처리를 유지합니다.

절충점: 최신 레코드보다 반복 코드가 많지만, C# 6에서도 명확하게 사용할 수 있습니다.

DU 에뮬레이션 방식

빠른 확인: C# 6에서 판별된 합집합을 흉내 내는 간단한 방법은 무엇입니까?

복습

복습: 태그 열거형으로 변형을 모델링하고, 팩터리를 통해 유효한 경우를 만든 다음, 런타임에 모든 경우를 처리할 수 있도록 스위치(기본값에서 예외 발생) 한곳에 처리를 모읍니다.

무료로 시작

AI 튜터와 함께 C#을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
93
레슨
346

자주 묻는 질문

“판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)” 강의는 무료인가요?

네 — “판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 3개의 강의가 포함되어 있습니다.

“판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)”에서 뭘 배우나요?

태그 열거형과 작은 클래스를 사용해 C# 6에서 판별 합집합을 모델링하고, 팩터리 메서드를 만들며, default에서 예외를 던지는 switch로 변형을 처리합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C# Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 3번째 강의입니다.

“판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. is 패턴과 관계·논리 패턴(C# 6 에뮬레이션)
  2. switch 식과 when을 사용한 모든 경우 검사(C# 6 에뮬레이션)
  3. 판별 합집합을 활용한 도메인 모델링(record)(C# 6 에뮬레이션)
← C# Academy(으)로 돌아가기