Panduan umum untuk C # adalah selalu menggunakan properti di bidang publik. Ini masuk akal - dengan mengekspos bidang, Anda mengekspos banyak detail implementasi. Dengan properti, Anda merangkum detail itu sehingga tersembunyi dari penggunaan kode, dan perubahan implementasi dipisahkan dari perubahan antarmuka.
Namun, saya bertanya-tanya apakah terkadang ada pengecualian yang valid untuk aturan ini ketika berhadapan dengan readonly
kata kunci. Dengan menerapkan kata kunci ini ke bidang publik, Anda membuat jaminan ekstra: imutabilitas. Ini bukan hanya detail implementasi, imutabilitas adalah sesuatu yang mungkin diminati konsumen. Menggunakan readonly
bidang menjadikannya bagian dari kontrak publik, dan sesuatu yang tidak dapat dipatahkan oleh perubahan atau pewarisan masa depan tanpa harus memodifikasi antarmuka publik. Itu sesuatu yang tidak bisa ditawarkan oleh properti.
Jadi, apakah jaminan ketidakmampuan merupakan alasan yang sah untuk memilih readonly
bidang daripada properti dalam beberapa kasus?
(Untuk klarifikasi, saya tentu tidak mengatakan Anda harus selalu membuat pilihan ini hanya karena lapangan terjadi menjadi berubah saat ini, hanya ketika masuk akal sebagai bagian dari desain kelas dan itu penggunaan dimaksudkan untuk mencakup kekekalan dalam kontrak. Saya sebagian besar tertarik pada jawaban yang fokus pada apakah ini dapat dibenarkan, daripada kasus-kasus tertentu di mana tidak, seperti ketika Anda membutuhkan anggota untuk berada di interface
, atau ingin melakukan pemuatan malas.)
sumber
Jawaban:
Bidang baca statis publik tentu saja oke. Mereka direkomendasikan untuk situasi tertentu, seperti ketika Anda menginginkan objek yang bernama dan konstan tetapi Anda tidak dapat menggunakan
const
kata kunci.Bidang anggota yang hanya baca agak sulit. Tidak ada banyak keuntungan yang diperoleh atas properti tanpa setter publik, dan ada kelemahan utama: bidang tidak bisa menjadi anggota antarmuka. Jadi, jika Anda memutuskan untuk membuat ulang kode untuk beroperasi dengan antarmuka alih-alih jenis konkret, Anda harus mengubah bidang yang hanya baca menjadi properti dengan getter publik.
Properti non-virtual publik tanpa setter yang dilindungi memberikan perlindungan terhadap warisan, kecuali kelas yang diwarisi memiliki akses ke bidang dukungan. Anda dapat sepenuhnya menegakkan kontrak itu di kelas dasar.
Tidak bisa mengubah "keabadian" anggota tanpa mengubah antarmuka publik kelas tidak banyak penghalang dalam kasus ini. Biasanya jika Anda ingin mengubah bidang publik menjadi properti, itu berjalan lancar kecuali bahwa ada dua kasus yang harus Anda tangani:
object.Location.X = 4
hanya mungkin jikaLocation
merupakan bidang. Ini tidak relevan untuk bidang hanya baca, karena Anda tidak dapat mengubah struct baca saja. (Ini dengan asumsiLocation
adalah tipe nilai - jika tidak maka masalah ini tidak akan berlaku karenareadonly
tidak melindungi terhadap hal semacam itu.)out
atauref
. Sekali lagi, ini tidak benar-benar relevan untuk bidang readonly, karenaout
danref
parameter cenderung dimodifikasi, dan ini merupakan kesalahan kompiler untuk meneruskan nilai readonly sebagai out atau ref.Dengan kata lain, meskipun mengonversi bidang baca menjadi properti baca hanya merusak kompatibilitas biner, kode sumber lain hanya perlu dikompilasi ulang tanpa perubahan apa pun untuk menangani perubahan ini. Itu membuat jaminan sangat mudah untuk dilanggar.
Saya tidak melihat kelebihan pada
readonly
bidang anggota, dan ketidakmampuan untuk memiliki hal semacam itu di antarmuka cukup merugikan bagi saya bahwa saya tidak akan menggunakannya.sumber
Dari pengalaman saya,
readonly
kata kunci bukanlah keajaiban yang dijanjikannya.Misalnya, Anda memiliki kelas di mana konstruktor dulu sederhana. Mengingat penggunaannya, (dan fakta bahwa beberapa properti / bidang kelas tidak dapat diubah setelah konstruksi) Anda mungkin berpikir bahwa itu tidak masalah, jadi Anda menggunakan
readonly
kata kunci.Kemudian, kelas menjadi lebih kompleks, dan begitu pula konstruktornya. (Katakanlah ini terjadi dalam proyek yang bersifat eksperimental atau memiliki kecepatan cukup tinggi zoom di luar ruang lingkup / kontrol tetapi Anda perlu membuatnya bekerja entah bagaimana.) Anda akan menemukan bahwa bidang yang
readonly
hanya dapat dimodifikasi di dalam konstruktor - Anda tidak dapat memodifikasinya dalam metode bahkan jika metode itu hanya dipanggil dari konstruktor.Keterbatasan teknis ini telah diakui oleh perancang C #, dan mungkin diperbaiki di versi mendatang. Tetapi sampai diperbaiki, penggunaan
readonly
lebih terbatas dan mungkin mendorong beberapa gaya pengkodean yang buruk (meletakkan semuanya dalam metode konstruktor).Sebagai pengingat, baik properti
readonly
non-publik-setter tidak memberikan jaminan atas "objek yang diinisialisasi penuh". Dengan kata lain, perancang kelaslah yang memutuskan apa yang dimaksud "diinisialisasi penuh", dan bagaimana melindunginya terhadap penggunaan yang tidak disengaja, dan perlindungan semacam itu pada umumnya tidak aman, yang berarti bahwa seseorang mungkin menemukan jalan keluarnya.sumber
readonly
bidang sebagai parameterout
atauref
ke metode lain, yang kemudian akan bebas untuk memodifikasinya sesuai keinginan mereka.Fields adalah SELALU detail implementasi. Anda tidak ingin mengekspos detail implementasi Anda.
Prinsip mendasar dari rekayasa perangkat lunak adalah bahwa kita tidak tahu apa persyaratannya di masa depan. Meskipun
readonly
bidang Anda mungkin bagus hari ini, tidak ada yang menyarankan bahwa itu akan menjadi bagian dari persyaratan besok. Bagaimana jika besok ada kebutuhan untuk menerapkan hit counter untuk menentukan berapa kali bidang itu diakses? Bagaimana jika Anda perlu mengizinkan sub-kelas untuk menimpa bidang?Properti sangat mudah digunakan dan jauh lebih fleksibel daripada bidang publik sehingga saya tidak bisa memikirkan satu kasus penggunaan di mana saya akan memilih c # sebagai bahasa saya dan menggunakan bidang yang hanya bisa dibaca publik di kelas. Jika kinerjanya sangat ketat sehingga saya tidak bisa menerima panggilan metode tambahan, saya mungkin akan menggunakan bahasa yang berbeda.
Hanya karena kita dapat melakukan sesuatu dengan bahasa itu tidak berarti kita harus melakukan sesuatu dengan bahasa itu.
Saya benar-benar bertanya-tanya apakah para perancang bahasa menyesal membiarkan bidang-bidang diumumkan kepada publik. Saya tidak ingat kapan terakhir kali saya mempertimbangkan untuk menggunakan bidang publik non-const dalam kode saya.
sumber
Rational
dengan publik, tidak berubahNumerator
danDenominator
anggota, saya bisa sangat yakin bahwa anggota tidak akan memerlukan pemuatan malas atau hit counter atau serupa?float
tipe untukNumerator
danDenominator
tidak perlu diubahdoubles
?float
ataudouble
. Mereka seharusnyaint
,long
atauBigInteger
. Mungkin itu perlu diubah ... tetapi jika demikian mereka harus berubah di antarmuka publik juga, jadi benar-benar menggunakan properti tidak menambahkan enkapsulasi di sekitar detail itu.Tidak. Itu bukan pembenaran.
Menggunakan readonly sebagai jaminan ketidakmungkinan untuk tidak dibenarkan lebih seperti peretasan.
Readonly berarti nilai diberikan oleh konstruktor o ketika variabel didefinisikan.
Saya pikir ini akan menjadi praktik yang buruk
Jika Anda benar-benar ingin menjamin kekekalan menggunakan antarmuka itu memiliki lebih banyak pro daripada kontra.
Contoh antarmuka sederhana:
sumber