0Pricing
C# Academy · Pelajaran

Immutability dengan init & with

Gunakan setter khusus init untuk membuat objek immutable dan ekspresi with untuk menghasilkan salinan yang dimodifikasi tanpa mengubah objek asli.

Immutability dengan init & with adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. 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 4 pelajaran total.

Apa Itu Kekekalan?

Objek yang tidak dapat diubah tidak dapat diubah setelah dibuat. Kekekalan mencegah perubahan yang tidak disengaja, membuat objek aman untuk utas secara bawaan, dan menyederhanakan penalaran tentang kode. C# menyediakan setter init dan ekspresi with agar penerapan kekekalan menjadi praktis.

Setter Khusus init

Akses init memungkinkan properti ditetapkan selama inisialisasi objek (melalui konstruktor atau penginisialisasi objek), tetapi tidak pernah setelahnya. Akses ini merupakan padanan yang tidak dapat diubah dari set.

public class Point
{
    public double X { get; init; }
    public double Y { get; init; }
}

var p = new Point { X = 3.0, Y = 4.0 }; // OK — init phase
p.X = 5.0; // COMPILE ERROR — cannot set after init

// All of these are valid init-phase assignments:
var p2 = new Point(X: 1.0, Y: 2.0);
var p3 = new Point { X = 0, Y = 0 };

init pada Properti Record Posisional

Properti record posisional secara bawaan hanya memiliki akses init—itulah yang membuat record tidak dapat diubah. Kompilator menghasilkan get; init; untuk setiap parameter posisional.

// This record:
public record Person(string Name, int Age);

// Is equivalent to:
public record Person
{
    public string Name { get; init; }
    public int Age    { get; init; }
    public Person(string Name, int Age) { this.Name = Name; this.Age = Age; }
    // + Deconstruct, Equals, GetHashCode, ToString
}

var alice = new Person("Alice", 30);
alice.Name = "Bob"; // COMPILE ERROR

Ekspresi with: Perubahan Non-Destruktif

Ekspresi with membuat salinan record dengan properti tertentu yang diubah. Record asli tidak berubah—itulah kekekalan yang sesungguhnya.

public record Person(string Name, int Age, string Email);

var alice = new Person("Alice", 30, "alice@example.com");

// Create a modified copy — alice is unchanged
var olderAlice = alice with { Age = 31 };
var renamed    = alice with { Name = "Alicia", Email = "alicia@example.com" };

Console.WriteLine(alice.Name);      // Alice (unchanged)
Console.WriteLine(olderAlice.Age);  // 31
Console.WriteLine(renamed.Name);    // Alicia

Ekspresi with pada Tipe Non-Record

C# 10 mengizinkan with pada struct atau kelas apa pun yang memiliki semantik konstruktor penyalinan, tetapi penggunaannya paling alami pada record. Untuk kelas, Anda perlu menerapkannya secara manual.

// struct with with-expression:
public struct Temperature
{
    public double Celsius { get; init; }
    public double Fahrenheit => Celsius * 9 / 5 + 32;
}

var t1 = new Temperature { Celsius = 20 };
var t2 = t1 with { Celsius = 25 }; // copy with change
Console.WriteLine(t1.Celsius); // 20 — unchanged
Console.WriteLine(t2.Celsius); // 25

Merangkai Ekspresi with

Rangkai beberapa ekspresi with untuk membangun transformasi kompleks. Setiap langkah membuat nilai tidak dapat diubah yang baru dari nilai sebelumnya.

public record Order(int Id, string Status, decimal Total, DateTime UpdatedAt);

var order = new Order(42, "Pending", 99.99m, DateTime.UtcNow);

// Apply a promotion discount then mark as confirmed
var finalOrder = order
    with { Total    = order.Total * 0.9m }    // 10% off
    with { Status   = "Confirmed" }
    with { UpdatedAt = DateTime.UtcNow };

Console.WriteLine(order.Status);     // Pending (original unchanged)
Console.WriteLine(finalOrder.Status); // Confirmed

Properti Terhitung pada Tipe yang Tidak Dapat Diubah

Properti turunan pada tipe yang tidak dapat diubah secara alami bersifat murni—properti tersebut dihitung dari nilai properti yang tetap dan selalu mengembalikan hasil yang sama untuk input yang sama.

public record Money(decimal Amount, string Currency)
{
    public Money Add(Money other)
    {
        if (Currency != other.Currency)
            throw new InvalidOperationException("Currency mismatch");
        return this with { Amount = Amount + other.Amount };
    }

    public Money Multiply(decimal factor) =>
        this with { Amount = Amount * factor };

    public override string ToString() =>
        $"{Amount:F2} {Currency}";
}

var price = new Money(10.00m, "USD");
var tax   = price.Multiply(0.08m);
var total = price.Add(tax);
Console.WriteLine(total); // 10.80 USD

Koleksi yang Tidak Dapat Diubah

Gabungkan record dengan ImmutableList<T> dan tipe lain dari System.Collections.Immutable untuk membentuk struktur data yang sepenuhnya tidak dapat diubah.

using System.Collections.Immutable;

public record ShoppingCart(
    string UserId,
    ImmutableList<CartItem> Items)
{
    public ShoppingCart AddItem(CartItem item) =>
        this with { Items = Items.Add(item) };

    public ShoppingCart RemoveItem(int productId) =>
        this with { Items = Items.RemoveAll(i => i.ProductId == productId) };

    public decimal Total => Items.Sum(i => i.Price * i.Quantity);
}

Keamanan Utas melalui Kekekalan

Objek yang tidak dapat diubah secara inheren aman untuk utas—tidak diperlukan sinkronisasi saat objek tersebut dibagikan antarutas karena statusnya tidak dapat berubah setelah konstruksi.

// Immutable config record shared across all threads safely
public record AppConfig(
    string ConnectionString,
    int MaxRetries,
    TimeSpan Timeout);

// Register as singleton — safe because record is immutable
builder.Services.AddSingleton(
    new AppConfig(
        ConnectionString: config["DB"]!,
        MaxRetries: 3,
        Timeout: TimeSpan.FromSeconds(30)));

// Any thread can read this simultaneously without locks

Dunia Nyata: Penyimpanan Berbasis Peristiwa Fungsional

Record yang tidak dapat diubah berpadu secara alami dengan penyimpanan berbasis peristiwa: setiap peristiwa domain tidak dapat diubah, dan status diturunkan dengan mengakumulasikan peristiwa—tanpa perubahan, tanpa kejutan.

public record OrderState(
    int Id,
    string Status = "Draft",
    decimal Total = 0m);

public static OrderState Apply(OrderState state, object evt) => evt switch
{
    OrderPlaced   e => state with { Status = "Pending", Total = e.Total },
    OrderShipped  _ => state with { Status = "Shipped" },
    OrderCancelled _ => state with { Status = "Cancelled" },
    _ => state
};

// Fold events to get current state:
var state = events.Aggregate(
    new OrderState(id),
    Apply);

Pemeriksaan Singkat

Apa yang dilakukan ekspresi 'with' terhadap record asli?

Ringkasan: Kekekalan dengan init & with

Kesimpulan utama:

  • Akses init: hanya dapat ditetapkan selama inisialisasi, tidak pernah setelahnya
  • Properti record posisional secara bawaan hanya memiliki akses init
  • Ekspresi with: membuat salinan yang diubah—record asli tidak berubah
  • Rangkai ekspresi with untuk transformasi dalam beberapa langkah
  • Tipe yang tidak dapat diubah aman untuk utas tanpa sinkronisasi
  • Gabungkan dengan ImmutableList<T> untuk membentuk graf objek yang sepenuhnya tidak dapat diubah

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Immutability dengan init & with” gratis?

Ya — teks lengkap “Immutability dengan init & with” 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 4 pelajaran total.

Apa yang akan aku pelajari di “Immutability dengan init & with”?

Gunakan setter khusus init untuk membuat objek immutable dan ekspresi with untuk menghasilkan salinan yang dimodifikasi tanpa mengubah objek asli. 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 2 dari 4.

Berapa lama pelajaran “Immutability dengan init & with” 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. Tipe Record: Dasar & Sintaks
  2. Immutability dengan init & with
  3. Kesetaraan Nilai & Dekonstruksi
  4. Record dalam Domain-Driven Design
← Kembali ke C# Academy