Apa manfaat memiliki variabel anggota yang dinyatakan sebagai hanya baca? Apakah itu hanya melindungi seseorang yang mengubah nilainya selama siklus hidup kelas atau apakah menggunakan kata kunci ini menghasilkan peningkatan kecepatan atau efisiensi?
295
readonly
bidang tipe struktur memaksakan penalti kinerja dibandingkan dengan bidang yang bisa berubah yang sama sekali tidak bermutasi, karena pemanggilan anggota mana pun darireadonly
bidang tipe nilai akan menyebabkan kompilator membuat salinan bidang dan meminta anggota itu.Jawaban:
Kata
readonly
kunci digunakan untuk mendeklarasikan variabel anggota sebagai konstanta, tetapi memungkinkan nilai tersebut dihitung saat runtime. Ini berbeda dari konstanta yang dideklarasikan denganconst
pengubah, yang harus ditetapkan nilainya pada waktu kompilasi. Menggunakanreadonly
Anda dapat mengatur nilai bidang baik dalam deklarasi, atau dalam konstruktor objek yang bidangnya anggota.Juga gunakan itu jika Anda tidak ingin harus mengkompilasi ulang DLL eksternal yang mereferensikan konstanta (karena akan diganti pada waktu kompilasi).
sumber
Saya tidak percaya ada keuntungan kinerja dari menggunakan bidang baca saja. Ini hanya pemeriksaan untuk memastikan bahwa setelah objek dibangun sepenuhnya, bidang itu tidak dapat diarahkan ke nilai baru.
Namun "readonly" sangat berbeda dari jenis semantik read-only lainnya karena diberlakukan saat runtime oleh CLR. Kata kunci yang hanya dibaca dikompilasi hingga .initonly yang dapat diverifikasi oleh CLR.
Keuntungan sebenarnya dari kata kunci ini adalah menghasilkan struktur data yang tidak dapat diubah. Struktur data yang tidak dapat berubah menurut definisi tidak dapat diubah begitu dibangun. Ini membuatnya sangat mudah untuk berpikir tentang perilaku struktur saat runtime. Misalnya, tidak ada bahaya menularkan struktur yang tidak dapat diubah ke bagian kode acak lainnya. Mereka tidak dapat mengubahnya sehingga Anda dapat memprogram dengan andal terhadap struktur itu.
Berikut adalah entri yang bagus tentang salah satu manfaat imutabilitas: Threading
sumber
Tidak ada manfaat kinerja yang jelas untuk digunakan
readonly
, setidaknya tidak ada yang pernah saya lihat disebutkan di mana saja. Itu hanya untuk melakukan persis seperti yang Anda sarankan, untuk mencegah modifikasi setelah diinisialisasi.Jadi ini bermanfaat karena membantu Anda menulis kode yang lebih kuat, lebih mudah dibaca. Manfaat nyata dari hal-hal seperti ini datang ketika Anda bekerja dalam tim atau untuk pemeliharaan. Mendeklarasikan sesuatu seperti
readonly
meletakkan kontrak untuk penggunaan variabel itu dalam kode. Anggap saja sebagai menambahkan dokumentasi dengan cara yang sama seperti kata kunci lain sukainternal
atauprivate
, Anda mengatakan "variabel ini tidak boleh dimodifikasi setelah inisialisasi", dan terlebih lagi Anda menegakkannya .Jadi, jika Anda membuat kelas dan menandai beberapa variabel anggota
readonly
dengan desain, maka Anda mencegah diri sendiri atau anggota tim lainnya membuat kesalahan nanti ketika mereka memperluas atau memodifikasi kelas Anda. Menurut pendapat saya, itu adalah manfaat yang berharga (dengan sedikit biaya kompleksitas bahasa tambahan seperti yang disebutkan oleh doofledorfer dalam komentar).sumber
Singkatnya:
Jika Anda menggunakan const di dll A dan dll B referensi const itu, nilai const itu akan dikompilasi menjadi dll B. Jika Anda memindahkan dll A dengan nilai baru untuk const itu, dll B masih akan menggunakan nilai asli.
Jika Anda menggunakan readonly di referensi A dan dll B dll yang hanya baca, readonly itu akan selalu dilihat saat runtime. Ini berarti jika Anda memindahkan dll A dengan nilai baru untuk readonly itu, dll B akan menggunakan nilai baru itu.
sumber
const
mungkin ada peningkatan kinerjareadonly
. Berikut ini penjelasan yang lebih dalam dengan kode: dotnetperls.com/readonlyreadonly
bidang. Anda tidak dapat menyimpannew object();
dalamconst
dan itu masuk akal karena Anda tidak dapat memanggang hal-hal yang tidak bernilai seperti referensi ke majelis lain selama waktu kompilasi tanpa mengubah identitas.Ada kasus potensial di mana kompiler dapat membuat pengoptimalan kinerja berdasarkan pada kehadiran kata kunci yang hanya dibaca.
Ini hanya berlaku jika bidang hanya baca juga ditandai sebagai statis . Dalam hal ini, kompiler JIT dapat mengasumsikan bahwa bidang statis ini tidak akan pernah berubah. Kompiler JIT dapat mempertimbangkan ini saat mengkompilasi metode kelas.
Contoh umum: kelas Anda bisa memiliki bidang IsDebugLoggingEnabled baca statis yang diinisialisasi dalam konstruktor (misalnya berdasarkan pada file konfigurasi). Setelah metode aktual dikompilasi JIT, kompiler dapat menghilangkan seluruh bagian kode ketika debug logging tidak diaktifkan.
Saya belum memeriksa apakah optimasi ini benar-benar diimplementasikan dalam versi JIT compiler saat ini, jadi ini hanya spekulasi.
sumber
Perlu diingat bahwa readonly hanya berlaku untuk nilai itu sendiri, jadi jika Anda menggunakan tipe referensi readonly hanya melindungi referensi dari perubahan. Keadaan instance tidak dilindungi oleh readonly.
sumber
Jangan lupa ada solusi untuk mendapatkan
readonly
bidang yang ditetapkan di luar konstruktor menggunakanout
params.Agak berantakan tapi:
Diskusi lebih lanjut di sini: http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx
sumber
out
..Anehnya, readonly sebenarnya dapat menghasilkan kode yang lebih lambat, seperti yang ditemukan Jon Skeet ketika menguji pustaka Noda Time-nya. Dalam kasus ini, tes yang berjalan dalam 20 detik hanya membutuhkan waktu 4 detik setelah menghapus hanya baca.
https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/
sumber
readonly struct
di C # 7.2, manfaat membuat bidang tidak dibaca hanya hilang.Jika Anda memiliki nilai yang ditentukan sebelumnya atau yang dihitung sebelumnya yang perlu tetap sama sepanjang program maka Anda harus menggunakan konstanta tetapi jika Anda memiliki nilai yang perlu diberikan pada saat runtime tetapi sekali ditugaskan harus tetap sama di seluruh program Anda harus menggunakan dibaca saja. misalnya jika Anda harus menetapkan waktu mulai program atau Anda harus menyimpan nilai yang disediakan pengguna pada inisialisasi objek dan Anda harus membatasi itu dari perubahan lebih lanjut yang harus Anda gunakan hanya baca.
sumber
Menambahkan aspek dasar untuk menjawab pertanyaan ini:
Properti dapat diekspresikan sebagai hanya dibaca dengan meninggalkan
set
operator. Jadi dalam kebanyakan kasus, Anda tidak perlu menambahkanreadonly
kata kunci ke properti:Berbeda dengan itu: Bidang membutuhkan
readonly
kata kunci untuk mencapai efek yang serupa:Jadi, satu manfaat dari menandai sebuah lapangan
readonly
adalah untuk mencapai tingkat perlindungan penulisan yang sama seperti properti tanpaset
operator - tanpa harus mengubah lapangan ke properti, jika karena alasan apa pun, yang diinginkan.sumber
Hati-hati dengan susunan baca baca pribadi. Jika ini mengekspos klien sebagai objek (Anda mungkin melakukan ini untuk COM interop seperti yang saya lakukan) klien dapat memanipulasi nilai array. Gunakan metode Clone () saat mengembalikan array sebagai objek.
sumber
ReadOnlyCollection<T>
bukan array.ImmutableArray<T>
, yang menghindari tinju ke antarmuka (IReadOnlyList<T>
) atau membungkus sebuah kelas (ReadOnlyCollection
). Ini memiliki kinerja yang sebanding dengan array asli: blogs.msdn.microsoft.com/dotnet/2013/06/24/…Mungkin ada manfaat kinerja di WPF, karena menghilangkan kebutuhan akan DependencyProperties yang mahal. Ini bisa sangat berguna dengan koleksi
sumber
Bagian lain yang menarik dari penggunaan tanda baca hanya dapat melindungi bidang dari inisialisasi dalam singleton.
misalnya dalam kode dari csharpindepth :
readonly memainkan peran kecil melindungi bidang Singleton dari diinisialisasi dua kali. Detail lain adalah bahwa untuk skenario yang disebutkan Anda tidak dapat menggunakan const karena const memaksa penciptaan selama waktu kompilasi, tetapi singleton membuat penciptaan pada saat run time.
sumber
readonly
dapat diinisialisasi pada saat deklarasi atau mendapatkan nilainya dari konstruktor saja. Berbeda denganconst
itu harus diinisialisasi dan menyatakan pada saat yang sama.readonly
memiliki semuanyaconst
, ditambah inisialisasi konstruktorkode https://repl.it/HvRU/1
sumber