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 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 memiliki init sebagai pengubah aksesnya. Aksesor set tersebut hanya dapat dipanggil dari penginisialisasi objek atau konstruktor jenis. Ini lebih ketat daripada private pada set aksesor.
  • Properti yang diimplementasikan secara otomatis dapat mendeklarasikan get aksesor tanpa set pengakses. Dalam hal ini, pengkompilasi memungkinkan set aksesor hanya dipanggil dari konstruktor jenis. Ini lebih ketat 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 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 atau init penganalisis.
  • 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