Akademi C# · Pelajaran

Ketidakbolehubahan dengan init & with

Gunakan setter init sahaja untuk mencipta objek tidak berubah dan ungkapan with untuk menghasilkan salinan yang diubah suai tanpa memusnahkan asal.

Pelajaran 2 daripada 412 langkah

Ketidakbolehubahan dengan init & with ialah pelajaran Akademi C# percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Akademi C#, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Akademi C# merangkumi sejumlah 4 pelajaran.

Apakah Itu Ketidakbolehubahan?

Objek tidak boleh diubah tidak boleh ditukar selepas dicipta. Ketidakbolehubahan menghalang perubahan tidak sengaja, menjadikan objek selamat untuk utas secara lalai dan memudahkan pemahaman tentang kod. C# menyediakan pengeset init dan ungkapan with untuk memudahkan pembinaan objek tidak boleh diubah.

Pengeset init Sahaja

Pengakses init membolehkan properti ditetapkan semasa pemulaan objek (dalam pembina atau pemula objek), tetapi tidak lagi selepas itu. Ia ialah padanan tidak boleh diubah bagi 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 dalam Properti Posisi Rekod

Properti posisi rekod secara lalai hanya mempunyai akses init — inilah yang menjadikan rekod tidak boleh diubah. Pengkompil menjana get; init; untuk setiap parameter posisi.

// 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

Ungkapan with: Perubahan Tanpa Memusnahkan Asal

Ungkapan with mencipta salinan rekod dengan properti tertentu yang diubah. Rekod asal tidak berubah — inilah ketidakbolehubahan sebenar.

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

with pada Jenis Bukan Rekod

C# 10 membenarkan with digunakan pada mana-mana struktur atau kelas yang mempunyai semantik pembina salinan — tetapi penggunaannya paling semula jadi dengan rekod. Bagi kelas, Anda perlu melaksanakannya 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

Rantaian Ungkapan with

Rantaikan beberapa ungkapan with untuk membina transformasi kompleks secara berperingkat; setiap langkah mencipta nilai tidak boleh diubah yang baharu daripada 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 Jenis Tidak Boleh Diubah

Properti terbitan pada jenis tidak boleh diubah sememangnya bersifat tulen — properti tersebut dikira daripada nilai properti yang tetap dan sentiasa memulangkan 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 Tidak Boleh Diubah

Gabungkan rekod dengan ImmutableList<T> dan jenis lain daripada System.Collections.Immutable untuk mendapatkan struktur data yang sepenuhnya tidak boleh 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);
}

Keselamatan Utas melalui Ketidakbolehubahan

Objek tidak boleh diubah sememangnya selamat untuk utas — tiada penyegerakan diperlukan apabila objek tersebut dikongsi merentas utas kerana state tidak boleh berubah selepas pembinaan.

// 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 Sebenar: Sumberan Acara Fungsian

Rekod tidak boleh diubah sememangnya sesuai dengan sumberan acara: setiap acara domain tidak boleh diubah, dan state diperoleh dengan melipat acara — tiada mutasi dan tiada 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);

Semakan Pantas

Apakah yang dilakukan oleh ungkapan 'with' terhadap rekod asal?

Ringkasan: Ketidakbolehubahan dengan init & with

Inti pati utama:

  • Pengakses init: hanya boleh ditetapkan semasa pemulaan, tidak pernah selepas itu
  • Properti posisi rekod secara lalai hanya mempunyai akses init
  • Ungkapan with: mencipta salinan yang diubah — rekod asal tidak berubah
  • Rantaikan ungkapan with untuk transformasi berbilang langkah
  • Jenis tidak boleh diubah selamat untuk utas tanpa penyegerakan
  • Gabungkan dengan ImmutableList<T> untuk graf objek yang sepenuhnya tidak boleh diubah
Percuma untuk bermula

Pelajari C# dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
93
Pelajaran
346

Soalan Lazim

Adakah pelajaran “Ketidakbolehubahan dengan init & with” percuma?

Ya — teks penuh “Ketidakbolehubahan dengan init & with” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Akademi C#, tingkat taraf kepada CoddyKit PRO. Kursus Akademi C# merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Ketidakbolehubahan dengan init & with”?

Gunakan setter init sahaja untuk mencipta objek tidak berubah dan ungkapan with untuk menghasilkan salinan yang diubah suai tanpa memusnahkan asal. Anda berlatih Akademi C# menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Akademi C#?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Akademi C# di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Ketidakbolehubahan dengan init & with” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Akademi C# ini?

Ya. Setiap pelajaran Akademi C# menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Jenis Record: Asas & Sintaks
  2. Ketidakbolehubahan dengan init & with
  3. Kesamaan Nilai & Penyahbinaan
  4. Record dalam Reka Bentuk Dipacu Domain
← Kembali ke Akademi C#