Properti otomatis hanya dengan pengambil, dapat diatur, mengapa?

97

Saya membuat properti otomatis:

public int Foo { get; } 

Ini hanya pengambil. Tetapi ketika saya membangun konstruktor, saya dapat mengubah nilainya:

public MyClass(string name)
{
    Foo = 5;
}

Mengapa mungkin, meskipun ini hanya untuk mendapatkan?

Noam B.
sumber
Ini tidak benar-benar menggunakan penyetel (karena tidak memilikinya). Ini secara langsung menetapkan bidang yang mendasarinya (yang tersembunyi dari kami, itulah sebabnya Anda perlu menggunakan nama properti)
Dennis_E
14
Apa gunanya properti, jika tidak pernah bisa diinisialisasi / disetel? Yacoub Massad telah menjawabnya dengan sempurna
Vikhram

Jawaban:

123

Ini adalah fitur C # 6 baru, "Getter-only auto-properties", juga dikenal sebagai "Auto-Property Initializers untuk Read-Only Properties" seperti yang dibahas dalam artikel majalah MSDN ini 'C #: The New and Improved C # 6.0' oleh Mark Michaelis dan dalam spesifikasi Bahasa draf C # 6.0 .

Penyetel bidang hanya baca hanya dapat diakses di konstruktor, dalam semua skenario lainnya, bidang masih hanya baca dan berperilaku seperti sebelumnya.

Ini adalah sintaks praktis untuk mengurangi jumlah kode yang perlu Anda ketik dan untuk menghilangkan kebutuhan untuk secara eksplisit mendeklarasikan variabel level modul privat untuk menampung nilai.

Fitur ini dipandang sama pentingnya dengan, sejak diperkenalkannya Properti yang Diimplementasikan Otomatis di C # 3, properti yang dapat diubah (yang memiliki pengambil dan penyetel) menjadi lebih cepat untuk menulis daripada yang tidak dapat diubah (yang hanya memiliki pengambil), artinya orang-orang tergoda untuk menggunakan properti yang bisa berubah untuk menghindari keharusan mengetik kode untuk bidang dukungan yang biasanya diperlukan untuk properti hanya-baca. Ada lebih banyak diskusi tentang properti yang Diimplementasikan Otomatis di bagian yang relevan dari Panduan Pemrograman Microsoft C # .

Postingan blog ini, '# 1,207 - C # 6.0 - Penginisialisasi Properti Otomatis untuk Properti Hanya-Baca' oleh Sean Sexton Memiliki penjelasan dan contoh yang baik sebagai berikut:

Sebelum C # 6.0, jika Anda menginginkan properti hanya-baca (tidak dapat diubah), Anda biasanya menggunakan bidang dukungan hanya-baca yang diinisialisasi dalam konstruktor, seperti yang ditunjukkan di bawah ini.

public class Dog 
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }

    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

Di C # 6.0, Anda dapat menggunakan properti yang diimplementasikan secara otomatis untuk mengimplementasikan properti hanya-baca. Anda melakukan ini dengan menggunakan penginisialisasi properti otomatis. Hasilnya jauh lebih bersih daripada contoh di atas, di mana kami harus secara eksplisit mendeklarasikan bidang dukungan.

public class Dog
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;

    public Dog(string name)
    {
        Name = name;
    }
}

Detail lebih lanjut juga dapat ditemukan di repo dotnet Roslyn di GitHub :

Properti otomatis sekarang dapat dideklarasikan tanpa penyetel.

Bidang dukungan dari properti otomatis khusus pengambil secara implisit dideklarasikan sebagai hanya baca (meskipun ini hanya penting untuk tujuan refleksi). Ini dapat diinisialisasi melalui penginisialisasi pada properti seperti pada contoh di atas. Selain itu, properti getter-only bisa ditetapkan ke dalam badan konstruktor tipe yang mendeklarasikan, yang menyebabkan nilai ditetapkan langsung ke bidang yang mendasarinya:

Ini tentang mengekspresikan tipe secara lebih ringkas, tetapi perhatikan bahwa ini juga menghilangkan perbedaan penting dalam bahasa antara tipe yang bisa berubah dan tipe yang tidak bisa diubah: properti-otomatis adalah singkatan yang hanya tersedia jika Anda ingin membuat kelas Anda bisa berubah, dan jadi godaan untuk default itu bagus. Sekarang, dengan properti otomatis khusus pengambil, bidang permainan telah diratakan antara dapat berubah dan tidak dapat diubah.

dan dalam draf C # 6.0 Spesifikasi Bahasa (NB: Spesifikasi bahasa adalah final sejauh menyangkut Microsoft, tetapi belum disetujui sebagai standar EMCA / ISO , oleh karena itu 'draf'):

Properti yang diterapkan secara otomatis

Properti yang diimplementasikan secara otomatis (atau disingkat properti otomatis), adalah properti non-abstrak non-eksternal dengan badan pengakses khusus titik koma. Properti otomatis harus memiliki aksesor get dan secara opsional dapat memiliki set pengakses.

Ketika sebuah properti ditetapkan sebagai properti yang diimplementasikan secara otomatis, bidang dukungan tersembunyi secara otomatis tersedia untuk properti tersebut, dan pengakses diimplementasikan untuk membaca dan menulis ke bidang dukungan tersebut. Jika properti otomatis tidak memiliki pengakses yang ditetapkan, bidang dukungan dianggap hanya baca (bidang Hanya baca). Sama seperti bidang hanya-baca, properti-otomatis khusus pengambil juga dapat ditetapkan ke dalam isi konstruktor kelas yang melingkupi. Penetapan seperti itu diberikan langsung ke bidang dukungan hanya baca dari properti.

Properti-otomatis secara opsional memiliki properti_inisialisasi, yang diterapkan langsung ke bidang dukungan sebagai variabel_inisialisasi (Penginisialisasi variabel).

tomRedox
sumber
1
Ini desain yang bodoh. Ini harus menjadi kesalahan waktu kompilasi jika disetel di lokasi di mana properti dianggap hanya-baca.
Shiv
Yang aneh bagi saya adalah masih ada kesalahan kompiler yang mengatakan CS0200 C# Property or indexer cannot be assigned to -- it is read onlysaat menggunakan properti biasa. Apakah "properti otomatis khusus pengambil" dianggap hanya baca atau tidak?
Kyle Delaney
24

Ini adalah fitur baru di C # 6 yang memungkinkan Anda membuat properti hanya-baca dan menginisialisasi nilainya dari konstruktor (atau sebaris saat Anda mendeklarasikannya).

Jika Anda mencoba mengubah nilai properti ini di luar konstruktor, itu akan memberi Anda kesalahan kompilasi.

Ini hanya-baca dalam arti bahwa setelah Anda menginisialisasi nilainya (sebaris atau di dalam konstruktor), Anda tidak dapat mengubah nilainya.

Yacoub Massad
sumber
Lantas apa penjelasannya? Apa definisi getter?
Noam B.
16

Jika tidak mungkin untuk menginisialisasi properti hanya-baca dari konstruktor (atau penginisialisasi properti otomatis), maka itu akan sia-sia, karena itu akan selalu mengembalikan nilai default untuk tipenya (0 untuk numerik, null untuk tipe referensi ). Semantik yang sama diterapkan ke bidang hanya baca di semua versi C #.

Untuk mendefinisikan properti getter-only (yang tidak dapat diinisialisasi dari konstruktor), Anda perlu menentukan apa yang dikembalikan sebagai bagian dari definisi:

public int Foo { get { return 5; } }

Atau, lebih tepatnya di C # 6:

public int Foo => 5;
Douglas
sumber
Tidak sepenuhnya benar, properti hanya baca sangat berguna untuk merangkum beberapa kondisi dalam kode Anda. Anda dapat menulis pernyataan if dan hampir semua kode untuk mengevaluasi properti atau kondisi lain dan mengembalikan nilai yang sesuai setiap kali Anda membaca properti
sebagomez
3
@sebagomez: Saya tidak yakin saya mengerti maksud Anda - bukankah itu yang saya tunjukkan dalam contoh saya?
Douglas
5

"Properti yang diterapkan secara otomatis hanya baca"

Pertama-tama saya ingin menjelaskan bahwa properti itu suka

public string FirstName { get; }

Dikenal sebagai "properti yang diterapkan secara otomatis hanya baca"

Untuk memverifikasi ini, Anda dapat menjalankan & memeriksa kode di atas dengan Visual Studio. Jika Anda mengubah versi bahasa dari C # 6.0 ke C # 5.0 maka compiler akan membuang pengecualian berikut Fitur 'properti yang diimplementasikan secara otomatis dapat dibaca' tidak tersedia di C # 5. Harap gunakan bahasa versi 6 atau lebih tinggi.

untuk mengubah versi bahasa C # kunjungi di sini

Sekarang saya sampai pada pertanyaan kedua Anda

“Ini hanya getter. Tapi ketika saya membangun konstruktor, saya bisa mengubah nilainya ”

Microsoft memperkenalkan "properti yang diimplementasikan secara otomatis baca" pada logika hanya baca. Seperti yang kita ketahui bahwa kata kunci “readonly” tersedia dari C # 1.0. kita menggunakan kata kunci "readonly" sebagai pengubah pada sebuah field dan field tersebut dapat diberikan dalam 2 cara baik pada saat deklarasi atau dalam sebuah konstruktor di kelas yang sama.

Dengan cara yang sama, nilai "properti yang diterapkan secara otomatis hanya baca" dapat ditetapkan dalam 2 cara

Way1 (pada saat deklarasi):

public string FirstName { get; } = "Banketeshvar";

Way2 (dalam konstruktor di kelas yang sama)

Person()
{
 FirstName  = "Banketeshvar";
}

Properti Hanya Baca Saja

Jika Anda mencari properti Readonly murni maka lakukanlah ini

public string FullName => "Manish Sharma";

sekarang Anda tidak dapat menetapkan nilai propery "FullName" dari konstruktor. Jika Anda mencoba melakukannya, pengecualian berikut akan muncul

"Properti atau pengindeks 'Person.FullName' tidak dapat ditetapkan ke - ini hanya baca"

Banketeshvar Narayan
sumber
2
perhatikan bahwa FullName => "foo bar" akan dievaluasi SETIAP WAKTU.
juFo
4

Fitur properti otomatis ditambahkan ke bahasa selama rilis C # 3.0. Ini memungkinkan Anda untuk menentukan properti tanpa bidang dukungan apa pun, namun Anda masih perlu menggunakan konstruktor untuk menginisialisasi properti otomatis ini ke nilai non-default. C # 6.0 memperkenalkan fitur baru yang disebut penginisialisasi properti otomatis yang memungkinkan Anda menginisialisasi properti ini tanpa konstruktor seperti di bawah ini:

Sebelumnya, konstruktor diperlukan jika Anda ingin membuat objek menggunakan properti otomatis dan menginisialisasi properti otomatis ke nilai non-default seperti di bawah ini:

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}

Sekarang di C # 6.0, kemampuan untuk menggunakan penginisialisasi dengan properti otomatis berarti tidak diperlukan kode konstruktor eksplisit.

public string Foo { get; } = "SomeString";

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

Anda dapat menemukan informasi lebih lanjut tentang ini di sini

Rahul Nikate
sumber
1

Variabel yang dideklarasikan readonlydapat ditulis dalam konstruktor, tetapi dalam bahasa yang menghormati atributnya, tidak dapat diubah setelah konstruktor kembali. Qualifier itu disediakan sebagai fitur bahasa karena sering kali diperlukan untuk bidang yang nilainya akan bervariasi berdasarkan parameter konstruktor (artinya mereka tidak dapat diinisialisasi sebelum konstruktor dimulai) tetapi tidak perlu berubah setelah konstruktor kembali, tapi itu hanya dapat digunakan untuk variabel yang diekspos sebagai bidang. Semantik darireadonly bidang -kualifikasi dalam banyak kasus akan sempurna untuk anggota publik kecuali bahwa seringkali lebih baik bagi kelas untuk mengekspos anggota - bahkan yang tidak dapat diubah - sebagai properti daripada bidang.

Seperti halnya properti otomatis baca-tulis yang memungkinkan kelas mengekspos properti yang dapat berubah semudah kolom biasa, properti otomatis hanya-baca juga ada untuk memungkinkan kelas mengekspos properti yang tidak dapat diubah semudah readonlykolom-kolom yang memenuhi syarat. Seperti readonlybidang yang memenuhi syarat dapat ditulis dalam konstruktor, demikian juga dengan properti get-only.

supercat
sumber