Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Ekspresi
Ekspresi with menghasilkan salinan operand-nya dengan properti dan bidang yang ditentukan yang dimodifikasi. Anda menggunakan sintaksis penginisialisasi objek
using System;
public class WithExpressionBasicExample
{
public record NamedPoint(string Name, int X, int Y);
public static void Main()
{
var p1 = new NamedPoint("A", 0, 0);
Console.WriteLine($"{nameof(p1)}: {p1}"); // output: p1: NamedPoint { Name = A, X = 0, Y = 0 }
var p2 = p1 with { Name = "B", X = 5 };
Console.WriteLine($"{nameof(p2)}: {p2}"); // output: p2: NamedPoint { Name = B, X = 5, Y = 0 }
var p3 = p1 with
{
Name = "C",
Y = 4
};
Console.WriteLine($"{nameof(p3)}: {p3}"); // output: p3: NamedPoint { Name = C, X = 0, Y = 4 }
Console.WriteLine($"{nameof(p1)}: {p1}"); // output: p1: NamedPoint { Name = A, X = 0, Y = 0 }
var apples = new { Item = "Apples", Price = 1.19m };
Console.WriteLine($"Original: {apples}"); // output: Original: { Item = Apples, Price = 1.19 }
var saleApples = apples with { Price = 0.79m };
Console.WriteLine($"Sale: {saleApples}"); // output: Sale: { Item = Apples, Price = 0.79 }
}
}
Operan kiri ekspresi with dapat berupa tipe rekaman . Operan sebelah kiri ekspresi with juga dapat berupa struktur jenis atau jenis anonim .
Hasil ekspresi with memiliki jenis run-time yang sama dengan operand ekspresi, seperti yang ditunjukkan contoh berikut:
using System;
public class InheritanceExample
{
public record Point(int X, int Y);
public record NamedPoint(string Name, int X, int Y) : Point(X, Y);
public static void Main()
{
Point p1 = new NamedPoint("A", 0, 0);
Point p2 = p1 with { X = 5, Y = 3 };
Console.WriteLine(p2 is NamedPoint); // output: True
Console.WriteLine(p2); // output: NamedPoint { X = 5, Y = 3, Name = A }
}
}
Saat anggota adalah jenis referensi, hanya referensi ke instans anggota yang disalin saat operand disalin. Salinan dan operand asli memiliki akses ke instans jenis referensi yang sama. Contoh berikut menunjukkan perilaku tersebut:
using System;
using System.Collections.Generic;
public class ExampleWithReferenceType
{
public record TaggedNumber(int Number, List<string> Tags)
{
public string PrintTags() => string.Join(", ", Tags);
}
public static void Main()
{
var original = new TaggedNumber(1, new List<string> { "A", "B" });
var copy = original with { Number = 2 };
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B
original.Tags.Add("C");
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B, C
}
}
Semantik salinan kustom
Kelas jenis rekaman apa pun memiliki konstruktor salinan . Konstruktor copy adalah konstruktor dengan parameter tunggal dari tipe record yang mengandung. Ini menyalin keadaan argumennya ke dalam sebuah instans rekaman baru. Pada evaluasi ekspresi with, konstruktor salinan dipanggil untuk membuat instans rekaman baru berdasarkan rekaman asli. Setelah itu, instans baru akan diperbarui sesuai dengan modifikasi yang ditentukan. Secara default, konstruktor salinan bersifat implisit, yaitu yang dihasilkan kompilator. Jika Anda perlu menyesuaikan semantik salinan rekaman, deklarasikan konstruktor salinan secara eksplisit dengan perilaku yang diinginkan. Contoh berikut memperbarui contoh sebelumnya dengan konstruktor salinan eksplisit. Perilaku penyalinan baru adalah menyalin item daftar alih-alih referensi daftar saat rekaman disalin:
using System;
using System.Collections.Generic;
public class UserDefinedCopyConstructorExample
{
public record TaggedNumber(int Number, List<string> Tags)
{
protected TaggedNumber(TaggedNumber original)
{
Number = original.Number;
Tags = new List<string>(original.Tags);
}
public string PrintTags() => string.Join(", ", Tags);
}
public static void Main()
{
var original = new TaggedNumber(1, new List<string> { "A", "B" });
var copy = original with { Number = 2 };
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B
original.Tags.Add("C");
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B
}
}
Anda tidak dapat menyesuaikan semantik penyalinan untuk tipe struktur.
Penting
Dalam contoh sebelumnya, semua properti independen. Tidak ada properti yang dihitung dari nilai properti lainnya. Ekspresi with terlebih dahulu menyalin instans rekaman yang ada, lalu memodifikasi properti atau bidang apa pun yang ditentukan dalam with ekspresi. Properti komputasi dalam record jenis harus dihitung pada akses, bukan diinisialisasi saat instans dibuat. Jika tidak, properti dapat mengembalikan nilai komputasi berdasarkan instans asli, bukan salinan yang dimodifikasi. Untuk informasi selengkapnya, lihat artikel referensi bahasa tentang record jenis.
Spesifikasi bahasa C#
Untuk informasi selengkapnya, lihat bagian berikut dari catatan proposal fiturdi catatan
-
ekspresi
with - anggota Salin dan Kloning