C# Academy · Pelajaran

Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6

Modelkan union terdiskriminasi dalam C# 6 menggunakan enum tag dan kelas-kelas kecil, buat metode pabrik, lalu tangani variannya melalui switch dengan lemparan default.

Pelajaran 3 dari 38 langkah

Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6 adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 3. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 3 pelajaran total.

Gagasan DU dalam C# 6

Tujuan: Bangun gabungan berpenanda kecil dalam C# 6.

  • Enum penanda untuk kasus aktif
  • Kelas kasus kecil untuk data
  • Metode Factory untuk membuat kasus yang valid
  • Percabangan + default yang melempar pengecualian untuk menangani semua varian

Penanda + Factory

Gunakan enum penanda dan metode Factory untuk membuat hanya kasus yang valid; kolom untuk kasus lain tetap tidak digunakan.

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);
  }
}

Menangani varian

Percabangan klasik berdasarkan penanda menghasilkan penanganan yang jelas. Default yang melempar pengecualian menampilkan varian yang belum ditangani selama pengujian.

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")));
  }
}

Pembantu Match (mirip pengunjung)

Pembantu kecil Match memusatkan percabangan dan mengembalikan nilai, sehingga lokasi pemanggil tetap rapi.

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);
  }
}

Invarian melalui Factory

Factory menegakkan invarian: setiap kasus hanya menginisialisasi kolom yang bermakna baginya; input yang tidak valid ditolak sejak awal.

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")));
  }
}

Kiat & kompromi

Kiat:

  • Utamakan kasus dan Factory yang kecil serta terfokus.
  • Tangani varian di satu tempat (pembantu percabangan) agar kode tetap DRY.
  • Pertahankan default yang melempar pengecualian untuk menampilkan kasus yang terlewat dalam pengujian.

Kompromi: Lebih banyak kode pendukung dibandingkan record modern, tetapi jelas dan kompatibel dengan C# 6.

Pendekatan peniruan DU

Pemeriksaan cepat: Dalam C# 6, apa cara sederhana untuk meniru gabungan berpenanda?

Ringkasan

Ringkasan: Modelkan varian dengan enum penanda, buat kasus yang valid melalui Factory, dan pusatkan penanganannya dalam percabangan (default melempar pengecualian) untuk memastikan kelengkapan saat runtime.

Gratis untuk memulai

Belajar C# dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
93
Pelajaran
346

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6” gratis?

Ya — teks lengkap “Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 3 pelajaran total.

Apa yang akan aku pelajari di “Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6”?

Modelkan union terdiskriminasi dalam C# 6 menggunakan enum tag dan kelas-kelas kecil, buat metode pabrik, lalu tangani variannya melalui switch dengan lemparan default. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai C# Academy?

Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 3.

Berapa lama pelajaran “Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?

Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Pola is; pola relasional & logika (emulasi C# 6)
  2. Ekspresi switch; pemeriksaan menyeluruh dengan when (emulasi C# 6)
  3. Pemodelan domain dengan union terdiskriminasi (record) — emulasi C# 6
← Kembali ke C# Academy