Properti (Panduan Pemrograman C#)
Properti adalah anggota yang menyediakan mekanisme fleksibel untuk membaca, menulis, atau menghitung nilai bidang data. Properti muncul sebagai anggota data publik, tetapi diimplementasikan sebagai metode khusus yang disebut pengakses. Fitur ini memungkinkan penelepon untuk mengakses data dengan mudah dan masih membantu mempromosikan keamanan dan fleksibilitas data. Sintaks untuk properti yaitu ekstensi alami ke bidang. Bidang mendefinisikan lokasi penyimpanan:
public class Person
{
public string? FirstName;
// Omitted for brevity.
}
Properti yang diimplementasikan secara otomatis
Definisi properti berisi deklarasi untuk pengakses get
dan set
yang mengambil dan menetapkan nilai properti tersebut:
public class Person
{
public string? FirstName { get; set; }
// Omitted for brevity.
}
Contoh sebelumnya menunjukkan properti yang diimplementasikan secara otomatis. Pengkompilasi menghasilkan bidang backing tersembunyi untuk properti . Kompilator juga mengimplementasikan isi pengakses get
dan set
. Atribut apa pun diterapkan ke properti yang diimplementasikan secara otomatis. Anda dapat menerapkan atribut ke bidang dukungan yang dihasilkan kompilator dengan menentukan field:
tag pada atribut .
Anda dapat menginisialisasi properti ke nilai selain default dengan mengatur nilai setelah kurung kurawal penutup untuk properti . Anda mungkin lebih suka nilai awal untuk FirstName
properti menjadi string kosong daripada null
. Anda akan menentukannya seperti yang ditunjukkan dalam kode berikut:
public class Person
{
public string FirstName { get; set; } = string.Empty;
// Omitted for brevity.
}
Kontrol akses
Contoh sebelumnya menunjukkan properti baca/tulis. Anda juga dapat membuat properti baca-saja, atau memberikan aksesibilitas yang berbeda ke set dan mendapatkan aksesor. Misalkan kelas Anda Person
hanya boleh mengaktifkan perubahan nilai properti dari metode lain di kelas tersebut FirstName
. Anda dapat memberikan aksesibilitas aksesor private
yang ditetapkan alih-alih public
:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
Properti FirstName
dapat dibaca dari kode apa pun, tetapi hanya dapat ditetapkan dari kode di Person
kelas .
Anda dapat menambahkan pengubah akses terbatas ke set atau mendapatkan aksesori. Pengubah akses pada aksesor individual harus lebih ketat daripada akses properti. Kode sebelumnya legal karena FirstName
propertinya adalah public
, tetapi aksesor yang ditetapkan adalah private
. Anda tidak dapat mendeklarasikan private
properti dengan public
aksesor. Deklarasi properti juga dapat dideklarasikan protected
, internal
, protected internal
, atau, bahkan private
.
Ada dua pengubah akses khusus untuk set
aksesor:
- Aksesor
set
dapat memilikiinit
sebagai pengubah aksesnya. Aksesorset
tersebut hanya dapat dipanggil dari penginisialisasi objek atau konstruktor jenis. Ini lebih ketat daripadaprivate
padaset
aksesor. - Properti yang diimplementasikan secara otomatis dapat mendeklarasikan
get
aksesor tanpaset
pengakses. Dalam hal ini, pengkompilasi memungkinkanset
aksesor hanya dipanggil dari konstruktor jenis. Ini lebih ketat daripadainit
aksesor padaset
aksesor.
Person
Ubah kelas sehingga sebagai berikut:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
Contoh sebelumnya mengharuskan penelepon untuk menggunakan konstruktor yang menyertakan FirstName
parameter . Penelepon tidak dapat menggunakan penginisialisasi objek untuk menetapkan nilai ke properti . Untuk mendukung penginisialisasi, Anda dapat menjadikan set
aksesor sebagai aksesor, seperti yang init
ditunjukkan dalam kode berikut:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
Pengubah ini sering digunakan dengan pengubah required
untuk memaksa inisialisasi yang tepat.
Properti yang diperlukan
Contoh sebelumnya memungkinkan pemanggil untuk membuat Person
menggunakan konstruktor default, tanpa mengatur FirstName
properti . Properti mengubah jenis menjadi untai (karakter) nullable . Mulai dari C# 11, Anda dapat mengharuskan penelepon untuk mengatur properti:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
// Omitted for brevity.
}
Kode sebelumnya membuat dua perubahan pada Person
kelas . Pertama, FirstName
deklarasi properti mencakup pengubah required
. Itu berarti kode apa pun yang membuat baru Person
harus mengatur properti ini menggunakan penginisialisasi objek. Kedua, konstruktor yang mengambil parameter memiliki firstName
System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute atribut . Atribut ini menginformasikan pengkompilasi bahwa konstruktor ini menetapkan semua required
anggota. Penelepon yang menggunakan konstruktor ini tidak diperlukan untuk mengatur required
properti dengan penginisialisasi objek.
Penting
Jangan bingung required
dengan non-nullable. Valid untuk mengatur required
properti ke null
atau default
. Jika jenisnya tidak dapat diubah ke null, seperti string
dalam contoh ini, pengkompilasi mengeluarkan peringatan.
var aPerson = new Person("John");
aPerson = new Person{ FirstName = "John"};
// Error CS9035: Required member `Person.FirstName` must be set:
//aPerson2 = new Person();
Definisi isi ekspresi
Aksesor properti sering terdiri dari pernyataan baris tunggal. Aksesor menetapkan atau mengembalikan hasil ekspresi. Anda dapat menerapkan properti ini sebagai anggota berisi ekspresi. Definisi isi ekspresi terdiri dari =>
token diikuti dengan ekspresi untuk ditetapkan atau diambil dari properti .
Properti baca-saja dapat mengimplementasikan get
aksesor sebagai anggota bertubuh ekspresi. Contoh berikut mengimplementasikan properti baca-saja Name
sebagai anggota bertubuh ekspresi:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public required string FirstName { get; init; }
public required string LastName { get; init; }
public string Name => $"{FirstName} {LastName}";
// Omitted for brevity.
}
Properti Name
adalah properti komputasi. Tidak ada bidang dukungan untuk Name
. Properti menghitungnya setiap kali.
Properti dengan bidang pendukung
Anda dapat mencampur konsep properti komputasi dengan bidang privat dan membuat properti yang dievaluasi cache. Misalnya, perbarui FullName
properti sehingga pemformatan string terjadi pada akses pertama:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public required string FirstName { get; init; }
public required string LastName { get; init; }
private string? _fullName;
public string FullName
{
get
{
if (_fullName is null)
_fullName = $"{FirstName} {LastName}";
return _fullName;
}
}
}
Implementasi ini berfungsi karena FirstName
properti dan LastName
secara baca-saja. Orang-orang dapat mengubah namanya. Memperbarui FirstName
properti dan LastName
untuk mengizinkan set
aksesor mengharuskan Anda membatalkan nilai cache apa pun untuk fullName
. Anda mengubah set
aksesor FirstName
properti dan LastName
sehingga fullName
bidang dihitung lagi:
public class Person
{
private string? _firstName;
public string? FirstName
{
get => _firstName;
set
{
_firstName = value;
_fullName = null;
}
}
private string? _lastName;
public string? LastName
{
get => _lastName;
set
{
_lastName = value;
_fullName = null;
}
}
private string? _fullName;
public string FullName
{
get
{
if (_fullName is null)
_fullName = $"{FirstName} {LastName}";
return _fullName;
}
}
}
Versi akhir ini mengevaluasi FullName
properti hanya jika diperlukan. Versi yang dihitung sebelumnya digunakan jika valid. Jika tidak, perhitungan memperbarui nilai yang di-cache. Pengembang yang menggunakan kelas ini tidak perlu mengetahui detail implementasinya. Tak satu pun dari perubahan internal ini mempengaruhi penggunaan objek Person.
Dimulai dengan C# 13, Anda dapat membuat partial
properti di partial
kelas. Deklarasi penerapan untuk partial
properti tidak dapat menjadi properti yang diimplementasikan secara otomatis. Properti yang diimplementasikan secara otomatis menggunakan sintaks yang sama dengan deklarasi properti parsial yang mendeklarasikan.
Properti
Properti adalah bentuk bidang pintar di kelas atau objek. Dari luar objek, mereka tampak seperti bidang dalam objek. Namun, properti dapat diimplementasikan menggunakan palet penuh fungsi C #. Anda dapat memberikan validasi, aksesibilitas yang berbeda, evaluasi malas, atau persyaratan apa pun yang dibutuhkan skenario Anda.
- Properti sederhana yang tidak memerlukan kode aksesor kustom dapat diimplementasikan baik sebagai definisi isi ekspresi atau sebagai properti yang diimplementasikan secara otomatis.
- Properti memungkinkan kelas memperlihatkan cara publik untuk mendapatkan dan menetapkan nilai, sambil menyembunyikan kode penerapan atau verifikasi.
- Pengakses properti get digunakan untuk mengembalikan nilai properti, dan pengakses properti set digunakan untuk menetapkan nilai baru. Aksesor properti init digunakan untuk menetapkan nilai baru hanya selama konstruksi objek. Pengakses ini dapat memiliki tingkat akses yang berbeda. Untuk informasi selengkapnya, lihat Membatasi Aksesibilitas Pengakses.
- Kata kunci nilai digunakan untuk menentukan nilai yang
set
ditetapkan atauinit
penganalisis. - Properti dapat berupa baca-tulis (properti memiliki pengakses
get
danset
), baca-saja (memiliki pengaksesget
tetapi tidak memiliki pengaksesset
), atau tulis-saja (memiliki pengaksesset
, tetapi tidak memiliki pengaksesget
). Properti khusus tulis jarang terjadi.
Spesifikasi Bahasa C#
Untuk informasi selengkapnya, lihat Properti di Spesifikasi Bahasa C#. Spesifikasi bahasa adalah sumber definitif untuk sintaks dan penggunaan C#.