Mulai menggunakan properti dan aksesor kelas
Properti kelas menyediakan mekanisme yang fleksibel untuk membaca, menulis, atau menghitung nilai bidang data. Mereka muncul sebagai anggota data publik, tetapi diimplementasikan sebagai metode khusus yang disebut aksesor . Fitur ini memungkinkan penelepon untuk mengakses data dengan mudah dan masih membantu mempromosikan keamanan dan fleksibilitas data.
Menggunakan properti
Properti menggabungkan aspek bidang dan metode. Untuk pengguna objek, properti tampaknya merupakan bidang. Mengakses properti memerlukan sintaks yang sama dengan mengakses bidang. Untuk pelaksana kelas, properti adalah satu atau dua blok kode, mewakili pengakses get dan/atau aksesor set atau init. Blok kode untuk aksesor get dijalankan saat properti dibaca. Blok kode untuk aksesor set atau init dijalankan saat properti diberi nilai. Properti tanpa aksesor set dianggap baca-saja. Properti tanpa aksesor get dianggap hanya tulis. Properti yang memiliki kedua aksesor adalah baca-tulis. Anda dapat menggunakan aksesor init alih-alih aksesor set untuk mengaktifkan properti untuk diatur sebagai bagian dari inisialisasi objek tetapi sebaliknya menjadikannya baca-saja.
Tidak seperti bidang, properti tidak diklasifikasikan sebagai variabel. Oleh karena itu, Anda tidak dapat meneruskan properti sebagai parameter ref atau out.
Properti sering digunakan untuk mendukung skenario berikut:
- Mereka dapat memvalidasi data sebelum mengizinkan perubahan.
- Mereka dapat mengekspos data secara transparan pada kelas tempat data tersebut diambil dari beberapa sumber lain, seperti database.
- Mereka dapat mengambil tindakan saat data diubah, seperti menaikkan peristiwa, atau mengubah nilai bidang lain.
Properti dideklarasikan dalam blok kode definisi kelas. Properti dideklarasikan dengan menentukan tingkat akses bidang, diikuti dengan jenis properti, diikuti dengan nama properti, diikuti dengan blok kode yang mendeklarasikan aksesor get dan/atau aksesor set.
Aksesor get
Isi aksesor get menyerupan metode. Ini harus mengembalikan nilai jenis properti. Pengkompilasi C# dan kompilator Just-in-time (JIT) mendeteksi pola umum untuk mengimplementasikan aksesor get, dan mengoptimalkan pola tersebut.
Misalnya, aksesor get yang mengembalikan bidang tanpa melakukan komputasi apa pun kemungkinan dioptimalkan untuk pembacaan memori bidang tersebut. Properti yang diimplementasikan secara otomatis, diperiksa di unit berikutnya dari modul ini, ikuti pola ini dan dapatkan manfaat dari pengoptimalan ini. Namun, metode aksesor get virtual tidak dapat di-inlin karena pengkompilasi tidak tahu pada waktu kompilasi metode mana yang mungkin benar-benar dipanggil pada waktu proses.
Contoh berikut menunjukkan aksesor get yang mengembalikan nilai bidang privat _name:
public class Employee
{
private string _name = "unknown"; // the name field
public string Name
{
get { return _name; } // the Name property
}
}
Dalam contoh ini, kelas Employee menyertakan bidang privat dan properti publik. Berikut adalah penjelasan tentang definisi kelas Employee:
- Kelas
Employeedidefinisikan dengan pengubah akses publik, yang berarti dapat diakses dari kode lain dalam rakitan yang sama atau rakitan lain yang mereferensikannya. - Bidang privat
_namedideklarasikan dengan jenisstringdan diberi nilai default,"unknown". - Properti publik
Namedideklarasikan dengan jenisstring. Properti menyertakan aksesorgetyang mengembalikan nilai bidang_name.
Nota
Bidang yang menyediakan nilai untuk aksesor properti sering disebut bidang backing .
Luangkan waktu satu menit untuk mempertimbangkan kode yang membuat instans objek Employee dan membaca nilai properti Name:
Employee employee = new Employee(); // create an instance of the Employee class
Console.Write(employee.Name); // use the get accessor to read the value of the Name property
Sampel kode ini membuat instans objek Employee baru bernama employee. Saat kode Anda mereferensikan properti employee.Name, kecuali sebagai target penugasan, aksesor get dipanggil untuk membaca nilai properti. Dalam hal ini, aksesor get mengembalikan nilai bidang _name, yang diberi nilai "unknown".
Blok kode untuk aksesor get juga dapat digunakan untuk mengembalikan nilai terhitung. Ini dapat berguna ketika Anda ingin memastikan bahwa properti selalu mengembalikan nilai non-null. Misalnya:
public class Manager
{
private string? _name;
public string Name
{
get
{
return _name != null ? _name : "NA";
}
}
}
Aksesor set
Aksesor set menyerupan metode yang jenis pengembaliannya batal. Ini menggunakan parameter implisit yang disebut value, yang jenisnya adalah jenis properti. Pengkompilasi dan pengkompilasi JIT juga mengenali pola umum untuk aksesor set atau init. Pola umum tersebut dioptimalkan, langsung menulis memori untuk bidang backing. Dalam contoh berikut, aksesor set ditambahkan ke properti Name:
class Student
{
private string? _name; // the name field
public string Name // the Name property
{
get
{
return _name != null ? _name : "NA";
}
set
{
_name = value;
}
}
}
Luangkan waktu satu menit untuk mempertimbangkan kode yang membuat instans kelas Student. Saat Anda menetapkan nilai ke properti Name, aksesor set dipanggil dengan menggunakan argumen yang menyediakan nilai baru. Misalnya:
var student = new Student();
student.Name = "StudentName"; // the set accessor is invoked here
Console.Write(student.Name); // the get accessor is invoked here
Aksesor init
Kode untuk membuat aksesor init sama dengan kode untuk membuat aksesor set kecuali Anda menggunakan kata kunci init alih-alih set. Perbedaannya adalah bahwa init aksesor hanya dapat digunakan di konstruktor atau dengan menggunakan penginisialisasi objek.
Mendeklarasikan dan menggunakan properti baca-tulis
Properti memberikan kenyamanan anggota data publik tanpa risiko yang disertakan dengan akses yang tidak terlindungi, tidak terkendali, dan tidak terverifikasi ke data objek. Properti mendeklarasikan aksesor: metode khusus yang menetapkan dan mengambil nilai dari anggota data yang mendasar. Aksesor set memungkinkan anggota data ditetapkan, dan aksesor get mengambil nilai anggota data.
Sampel ini menunjukkan kelas Person yang memiliki dua properti: Name (string) dan Age (int). Kedua properti menyediakan aksesor get dan set, sehingga dianggap sebagai properti baca/tulis.
class Person
{
private string _name = "N/A";
private int _age = 0;
// Declare a Name property of type string:
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
// Declare an Age property of type int:
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object named person:
Person person = new Person();
// Print out the default name and age of the person:
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Set some values on the person object:
person.Name = "PersonName";
person.Age = 99;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Increment the Age property:
person.Age += 1;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = PersonName, Age = 99
Person details - Name = PersonName, Age = 100
*/
Sintaksis aksesor dan teknik pengkodan
Selain sintaks dasar untuk mendeklarasikan properti, C# menyertakan sintaks yang memungkinkan Anda menulis kode yang lebih ringkas dan ekspresif. Fitur-fitur ini meliputi:
- Anggota bertubuh ekspresi
- Properti yang didukung bidang
- Properti yang diperlukan
Anggota bertubuh ekspresi
Anggota bertubuh ekspresi memberikan sintaks yang lebih ringkas untuk menulis aksesor properti baris tunggal.
Nota
Anggota bertubuh ekspresi juga dapat diterapkan ke metode, pengindeks, dan pengakses peristiwa.
Aksesor properti sering terdiri dari pernyataan baris tunggal yang menetapkan atau mengembalikan hasil ekspresi. Kelas Person yang Anda periksa sebelumnya di unit ini adalah contoh yang baik:
class Student
{
private string? _name; // the name field
public string Name // the Name property
{
get
{
return _name != null ? _name : "NA";
}
set
{
_name = value;
}
}
}
Dalam contoh ini, properti Name menggunakan pernyataan baris tunggal untuk mengembalikan nilai bidang _name jika bukan null, atau string "NA" jika null. Aksesor set menggunakan pernyataan satu baris untuk menetapkan nilai properti Name ke bidang _name.
Definisi isi ekspresi terdiri dari token => diikuti dengan ekspresi yang digunakan untuk menetapkan atau mengambil nilai properti. Karena aksesor yang ditentukan untuk kelas Student menerapkan pernyataan satu baris, ini adalah kandidat yang baik untuk pembaruan menggunakan definisi isi ekspresi.
Cuplikan kode berikut memperbarui kelas Student menggunakan definisi isi ekspresi untuk pengakses get dan set:
class Student
{
private string? _name; // the name field
public string Name // the Name property
{
get => _name ?? "NA";
set => _name = value;
}
}
Properti yang didukung bidang
Mulai dari C# 13, Anda dapat menambahkan validasi atau logika lain di aksesor untuk properti menggunakan fitur pratinjau kata kunci field. Kata kunci field mengakses bidang backing yang disintesis kompilator untuk properti. Ini memungkinkan Anda menulis aksesor properti tanpa secara eksplisit mendeklarasikan bidang dukungan terpisah.
public class Person
{
public string? FirstName
{
get;
set => field = value.Trim();
}
// Omitted for brevity.
}
Penting
Kata kunci field adalah fitur pratinjau di C# 13. Anda harus menggunakan .NET 9 dan mengatur elemen <LangVersion> Anda untuk dipratinjau dalam file proyek Anda untuk menggunakan kata kunci kontekstual field.
Anda harus berhati-hati menggunakan fitur kata kunci field di kelas yang memiliki bidang bernama field. Kata kunci field baru membayangi bidang bernama field dalam cakupan aksesor properti. Anda dapat mengubah nama variabel field, atau menggunakan token @ untuk mereferensikan pengidentifikasi bidang sebagai @field.
Properti yang diperlukan
Contoh sebelumnya memungkinkan pemanggil membuat Person menggunakan konstruktor default, tanpa mengatur properti FirstName. Jenis properti diatur ke string 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 kelas Person. Pertama, deklarasi properti FirstName mencakup pengubah required. Itu berarti kode apa pun yang membuat Person baru harus mengatur properti ini menggunakan penginisialisasi objek. Kedua, konstruktor yang mengambil parameter firstName memiliki atribut System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute. Atribut ini menginformasikan pengkompilasi bahwa konstruktor ini menetapkan semua anggota yang diperlukan. Penelepon yang menggunakan konstruktor ini tidak diperlukan untuk mengatur properti required dengan penginisialisasi objek.
Penting
Jangan bingung required dengan non-nullable. Valid untuk mengatur properti required ke null atau default. Jika jenisnya tidak dapat diubah ke null, seperti string dalam contoh ini, pengkompilasi mengeluarkan peringatan.
var aPerson = new Person("PersonName");
aPerson = new Person{ FirstName = "PersonName"};
// Error CS9035: Required member `Person.FirstName` must be set:
//aPerson2 = new Person();