Bagikan melalui


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 diwujudkan dalam bentuk fungsi khusus yang disebut pengakses. Fitur ini memungkinkan penelepon untuk mengakses data dengan mudah dan masih membantu mempromosikan keamanan dan fleksibilitas data. Sintaks untuk properti merupakan perpanjangan alami dari field. 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 lapangan pendukung 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 nilai default dengan mengatur nilai tersebut 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.
}

Properti yang didukung bidang

Di C# 13, Anda dapat menambahkan validasi atau logika lain di aksesor untuk properti menggunakan field fitur pratinjau kata kunci. Kata kunci field mengakses bidang penyimpanan yang dibuat oleh 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 field kunci adalah fitur pratinjau di C# 13. Anda harus menggunakan .NET 9 dan mengatur elemen Anda <LangVersion> ke preview dalam file proyek Anda untuk menggunakan field kata kunci kontekstual.

Anda harus berhati-hati menggunakan field fitur kata kunci di kelas yang memiliki bidang bernama field. Kata kunci baru field menutupi kolom bernama field dalam lingkup aksesor properti. Anda dapat mengubah nama field variabel, atau menggunakan @ token untuk mereferensikan field pengidentifikasi sebagai @field. Anda dapat mempelajari lebih lanjut dengan membaca spesifikasi fitur untuk field kata kunci.

Properti yang diperlukan

Contoh sebelumnya memungkinkan pemanggil untuk membuat Person menggunakan konstruktor default, tanpa mengatur FirstName properti . Jenis properti berubah menjadi string yang dapat bernilai null. 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, 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 semuarequired anggota. Penelepon yang menggunakan konstruktor ini tidak harus mengatur properti required dengan penginisialisasi objek.

Penting

Jangan bingung required dengan non-nullable. Sah untuk menetapkan properti required menjadi 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 yang menggunakan 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 pendukung untuk Name. Properti menghitungnya setiap kali.

Kontrol akses

Contoh sebelumnya menunjukkan properti baca/tulis. Anda juga dapat membuat properti yang hanya bisa dibaca, atau memberikan aksesibilitas yang berbeda untuk set dan get aksesornya. Misalkan kelas Anda Person hanya boleh memungkinkan perubahan nilai properti FirstName dari metode lain di dalam kelas. Anda dapat memberikan aksesibilitas aksesor private yang ditetapkan alih-alih internal atau 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 pembatas akses ke accessor set atau get. Pengubah akses pada aksesori individual harus lebih terbatas 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-pengubah akses khusus yang ada untuk set aksesor:

  • Aksesor set dapat memiliki init sebagai pengubah aksesnya. Aksesor set tersebut hanya dapat dipanggil dari penginisialisasi objek atau konstruktor tipe. Ini lebih ketat daripada private pada set aksesor.
  • Properti yang diimplementasikan secara otomatis dapat mendeklarasikan get aksesor tanpa set pengakses. Dalam hal ini, kompilator memungkinkan set aksesor hanya dipanggil dari konstruktor dari tipe tersebut. Ini lebih terbatas daripada init aksesor pada set 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 mengubah set aksesor menjadi init aksesor, seperti yang 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 bersama pengubah required untuk memastikan inisialisasi yang benar.

Properti dengan lapangan 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 properti FirstName dan LastName adalah hanya-baca. Orang-orang dapat mengubah namanya. Memperbarui properti FirstName dan LastName untuk mengizinkan akses pengubah set mengharuskan Anda membatalkan setiap nilai cache untuk fullName. Anda mengubah aksesor set dari properti FirstName dan LastName sehingga bidang fullName 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. Tidak ada perubahan internal ini yang 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.

Properti

Properti adalah bentuk atribut cerdas 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 tunda, atau persyaratan apa pun yang diperlukan oleh 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. Aksesori properti init digunakan untuk menetapkan nilai baru hanya saat proses 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 ditetapkan pengakses set atau init.
  • Properti dapat berupa baca-tulis (properti memiliki pengakses get dan set), baca-saja (memiliki pengakses get tetapi tidak memiliki pengakses set), atau tulis-saja (memiliki pengakses set, tetapi tidak memiliki pengakses get). 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#.

Lihat juga