@donstack, sebenarnya sesuai dengan referensi C # , bidang baca hanya dapat ditugaskan dan dipindahkan beberapa kali dalam deklarasi dan konstruktor bidang.
Marques
Jawaban:
1289
Terlepas dari perbedaan nyata
harus mendeklarasikan nilai pada saat definisi untuk nilai constVS readonlydapat dihitung secara dinamis tetapi perlu ditugaskan sebelum konstruktor keluar .. setelah itu dibekukan.
'const secara implisit static. Anda menggunakan ClassName.ConstantNamenotasi untuk mengaksesnya.
Ada perbedaan yang halus. Pertimbangkan kelas yang didefinisikan dalam AssemblyA.
AssemblyBreferensi AssemblyAdan menggunakan nilai-nilai ini dalam kode. Ketika ini dikompilasi,
dalam hal constnilai, itu seperti mencari-ganti, nilai 2 'dimasukkan ke dalam AssemblyB' IL yang ada. Ini berarti bahwa jika besok saya akan memperbarui I_CONST_VALUEke 20 di masa mendatang. AssemblyBmasih akan memiliki 2 sampai saya kompilasi ulang .
dalam hal readonlynilai, itu seperti refke lokasi memori. Nilai tidak dimasukkan ke AssemblyBIL. Ini berarti bahwa jika lokasi memori diperbarui, AssemblyBdapatkan nilai baru tanpa kompilasi ulang. Jadi, jika I_RO_VALUEdiperbarui ke 30, Anda hanya perlu membangun AssemblyA. Semua klien tidak perlu dikompilasi ulang.
Jadi, jika Anda yakin bahwa nilai konstanta tidak akan berubah, gunakan a const.
publicconstint CM_IN_A_METER =100;
Tetapi jika Anda memiliki konstanta yang dapat berubah (misalnya presisi) .. atau jika ragu, gunakan a readonly.
publicreadonlyfloat PI =3.14;
Update: Aku perlu disebutkan karena dia menunjukkan ini dulu. Saya juga perlu menghubungkan di mana saya belajar ini .. Efektif C # - Bill Wagner
The statictitik tampaknya menjadi titik paling penting dan berguna -consts are implicitly static
LCJ
28
Bagian tentang nilai referensi adalah yang paling penting. Nilai-nilai Const dapat dioptimalkan jauh.
CodingBarfield
22
readonlyvariabel dapat diubah di luar konstruktor (refleksi). Hanya kompiler yang mencoba menghalangi Anda untuk memodifikasi var di luar konstruktor.
Bitterblue
12
readonlyVariabel @ mini-me tidak diperbolehkan untuk diubah setelah konstruktor selesai, bahkan melalui refleksi. Runtime terjadi untuk tidak menegakkan ini. Runtime juga terjadi tidak untuk menegakkan bahwa Anda tidak mengubah string.Emptyke "Hello, world!", tapi aku masih tidak akan mengklaim bahwa ini membuat string.Emptydimodifikasi, atau kode yang tidak boleh berasumsi bahwa string.Emptyakan selalu menjadi nol-panjang string.
Ada gotcha dengan const! Jika Anda mereferensikan konstanta dari rakitan lain, nilainya akan dikompilasi langsung ke rakitan panggilan. Dengan begitu ketika Anda memperbarui konstanta dalam rakitan yang direferensikan itu tidak akan berubah dalam rakitan panggilan!
Pada dekompilasi (Reflektor, ILSpy, ..) konstanta TIDAK PERNAH direferensikan oleh siapa pun, tidak peduli perakitan yang sama atau perakitan lain, jadi Anda tidak dapat menganalisis penggunaan konstanta dalam kode yang dikompilasi sama sekali.
springy76
159
Konstanta
Konstanta statis secara default
Mereka harus memiliki nilai pada waktu kompilasi (Anda dapat memiliki mis. 3.14 * 2, tetapi tidak dapat memanggil metode)
Dapat dideklarasikan dalam fungsi
Disalin ke setiap majelis yang menggunakannya (setiap majelis mendapat salinan nilai lokal)
Dapat digunakan dalam atribut
Baca hanya bidang contoh
Harus memiliki nilai yang ditetapkan, saat konstruktor keluar
Dievaluasi ketika instance dibuat
Bidang baca statis saja
Dievaluasi ketika eksekusi kode mencapai referensi kelas (ketika instance baru dibuat atau metode statis dijalankan)
Harus memiliki nilai yang dievaluasi pada saat konstruktor statis selesai
Tidak disarankan untuk menempatkan ThreadStaticAttribute pada ini (konstruktor statis akan dieksekusi dalam satu utas saja dan akan menetapkan nilai utasnya; semua utas lainnya akan memiliki nilai ini diinisialisasi)
Sekadar menambahkan, ReadOnly untuk tipe referensi hanya membuat referensi menjadi bukan nilai. Sebagai contoh:
publicclassConst_V_Readonly{publicconstint I_CONST_VALUE =2;publicreadonlychar[] I_RO_VALUE =newChar[]{'a','b','c'};publicUpdateReadonly(){
I_RO_VALUE[0]='V';//perfectly legal and will update the value
I_RO_VALUE =newchar[]{'V'};//will cause compiler error}}
Apakah ada jenis referensi selain stringyang bisa Anda gunakan sebagai konstanta?
springy76
Anda dapat memiliki constdengan tipe referensi selain string, tetapi konstanta hanya dapat memiliki nilai null.
Mike Rosoft
40
Ini menjelaskannya . Ringkasan: const harus diinisialisasi pada waktu deklarasi, readonly dapat diinisialisasi pada konstruktor (dan dengan demikian memiliki nilai yang berbeda tergantung pada konstruktor yang digunakan).
EDIT: Lihat Gotcha Gishu di atas untuk perbedaan halus
Ada gotcha kecil dengan readonly. Bidang readonly dapat disetel beberapa kali dalam konstruktor. Sekalipun nilainya diatur dalam dua konstruktor berantai yang berbeda, ia tetap diizinkan.
publicclassSample{privatereadonlystring ro;publicSample(){
ro ="set";}publicSample(stringvalue):this(){
ro =value;// this works even though it was set in the no-arg ctor}}
Anggota konstan didefinisikan pada waktu kompilasi dan tidak dapat diubah pada saat runtime. Konstanta dinyatakan sebagai bidang, menggunakan constkata kunci dan harus diinisialisasi seperti yang dinyatakan.
Seorang readonlyanggota adalah seperti konstanta karena mewakili nilai yang tidak berubah. Perbedaannya adalah bahwa readonlyanggota dapat diinisialisasi pada saat runtime, dalam sebuah konstruktor, dan juga dapat diinisialisasi seperti yang dideklarasikan.
Mereka tidak bisa statis , mereka statis. Anda harus memperjelas jika maksud Anda seseorang tidak dapat mendeklarasikanstatic const int i = 0;
nawfal
Bisakah Anda menjelaskan mengapa constdeklarasi tidak bisa dibuat di dalam metode?
Minh Tran
21
Const adalah konstanta waktu kompilasi sedangkan readonly memungkinkan nilai untuk dihitung pada saat run-time dan ditetapkan dalam konstruktor atau penginisialisasi bidang. Jadi, 'const' selalu konstan tetapi 'readonly' adalah read-only setelah ditugaskan.
Eric Lippert dari tim C # memiliki informasi lebih lanjut tentang berbagai jenis ketidakberdayaan
Ini tautan lain menunjukkan bagaimana const tidak aman untuk versi, atau relevan untuk tipe referensi.
Ringkasan :
Nilai properti const Anda ditetapkan pada waktu kompilasi dan tidak dapat berubah saat runtime
Const tidak dapat ditandai sebagai statis - kata kunci menunjukkan mereka statis, tidak seperti bidang hanya baca yang bisa.
Const tidak bisa apa pun kecuali tipe nilai (primitif)
Kata kunci yang hanya dibaca menandai bidang sebagai tidak dapat diubah. Namun properti dapat diubah di dalam konstruktor kelas
Kata kunci hanya baca juga dapat dikombinasikan dengan statis untuk membuatnya bertindak dengan cara yang sama dengan const (minimal di permukaan). Ada perbedaan yang nyata ketika Anda melihat IL di antara keduanya
bidang const ditandai sebagai "literal" dalam IL sedangkan readonly adalah "initonly"
Saya percaya constnilai adalah sama untuk semua objek (dan harus diinisialisasi dengan ekspresi literal), sedangkan readonlydapat berbeda untuk setiap instantiation ...
Salah satu anggota tim di kantor kami memberikan panduan berikut tentang kapan harus menggunakan const, statis, dan hanya baca:
Gunakan const ketika Anda memiliki variabel tipe yang dapat Anda ketahui saat runtime (string literal, int, double, enums, ...) yang Anda inginkan agar semua instance atau konsumen kelas memiliki akses ke tempat nilainya tidak boleh berubah.
Gunakan statis ketika Anda memiliki data yang Anda inginkan semua instance atau konsumen kelas memiliki akses ke tempat nilai dapat berubah.
Gunakan pembacaan statis ketika Anda memiliki variabel tipe yang tidak dapat Anda ketahui saat runtime (objek) yang Anda inginkan semua instance atau konsumen kelas memiliki akses ke tempat nilainya tidak boleh berubah.
Gunakan hanya baca ketika Anda memiliki variabel tingkat contoh Anda akan tahu pada saat pembuatan objek yang tidak boleh berubah.
Satu catatan terakhir: bidang const adalah statis, tetapi kebalikannya tidak benar.
Saya pikir maksud Anda "berbicara." Kebalikannya adalah "bidang non-const tidak statis." Yang mungkin atau mungkin tidak benar. Kebalikannya, "bidang statis (selalu) const" tidak benar.
Michael Blackburn
5
Keduanya konstan, tetapi const tersedia juga pada waktu kompilasi. Ini berarti bahwa salah satu aspek dari perbedaan adalah bahwa Anda dapat menggunakan variabel const sebagai input ke atribut constructor, tetapi tidak hanya variabel readonly.
Contoh:
publicstaticclassText{publicconststringConstDescription="This can be used.";publicreadonlystaticstringReadonlyDescription="Cannot be used.";}publicclassFoo{[Description(Text.ConstDescription)]publicintBarThatBuilds{{get;set;}}[Description(Text.ReadOnlyDescription)]publicintBarThatDoesNotBuild{{get;set;}}}
Variabel bertanda const sedikit lebih banyak daripada makro #define yang diketik dengan kuat, pada waktu kompilasi variabel referensi const diganti dengan nilai literal sebaris. Sebagai akibatnya, hanya tipe nilai primitif bawaan tertentu yang dapat digunakan dengan cara ini. Variabel bertanda readonly dapat diatur, dalam konstruktor, pada saat run-time dan read-only-ness mereka diberlakukan selama run-time juga. Ada beberapa biaya kinerja kecil yang terkait dengan ini tetapi itu berarti Anda dapat menggunakan hanya baca dengan tipe apa pun (tipe referensi genap).
Juga, variabel const secara inheren statis, sedangkan variabel readonly dapat spesifik misalnya jika diinginkan.
Menambahkan bahwa consts sangat diketik #define macro. Kalau tidak, kami dapat menakuti semua orang C atau C ++. :-)
Jason Baker
4
CONST
kata kunci const dapat diterapkan ke bidang atau variabel lokal
Kita harus menetapkan bidang const pada saat deklarasi
No Memory Allocated Karena nilai const tertanam dalam kode IL itu sendiri setelah kompilasi. Ini seperti menemukan semua kemunculan variabel const dan ganti nilainya. Jadi kode IL setelah kompilasi akan memiliki nilai-nilai hard-code di tempat variabel const
Konstanta di C # secara default statis.
Nilainya konstan untuk semua objek
Ada masalah versi dll - Ini berarti bahwa setiap kali kita mengubah variabel atau properti const publik, (Sebenarnya, itu tidak seharusnya diubah secara teoritis), dll atau perakitan lain yang menggunakan variabel ini harus dibangun kembali
Hanya tipe bawaan C # yang dapat dinyatakan sebagai konstan
Bidang Const tidak dapat diteruskan sebagai parameter ref atau out
Baca Saja
kata kunci readonly hanya berlaku untuk bidang bukan variabel lokal
Kita dapat menetapkan bidang hanya baca pada saat deklarasi atau dalam konstruktor, bukan dalam metode lain.
memori dinamis dialokasikan untuk bidang yang hanya bisa dibaca dan kita bisa mendapatkan nilainya saat dijalankan.
Readonly adalah milik objek yang dibuat sehingga diakses hanya melalui instance kelas. Untuk menjadikannya anggota kelas, kita perlu menambahkan kata kunci statis sebelum dibaca.
Nilai mungkin berbeda tergantung pada konstruktor yang digunakan (karena itu milik objek kelas)
Jika Anda mendeklarasikan tipe non-primitif (tipe referensi) sebagai referensi hanya baca yang tidak berubah, bukan objek yang dikandungnya.
Karena nilai diperoleh pada saat dijalankan, tidak ada masalah versi dll dengan bidang / properti hanya baca.
Kita dapat melewati bidang hanya baca sebagai parameter ref atau out dalam konteks konstruktor.
Karena const benar-benar hanya bekerja dengan tipe data dasar, jika Anda ingin bekerja dengan kelas, Anda mungkin merasa "dipaksa" untuk menggunakan ReadOnly. Namun, waspadalah terhadap jebakan! ReadOnly berarti Anda tidak dapat mengganti objek dengan objek lain (Anda tidak dapat membuatnya merujuk ke objek lain). Tetapi setiap proses yang memiliki referensi ke objek bebas untuk mengubah nilai-nilai di dalam objek!
Jadi jangan bingung untuk berpikir bahwa ReadOnly menyiratkan pengguna tidak dapat mengubah hal-hal. Tidak ada sintaksis sederhana dalam C # untuk mencegah instantiasi suatu kelas agar nilai internalnya berubah (sejauh yang saya tahu).
Ya itu lebih merupakan tema umum. Jika Anda hanya mendapatkan properti yang mengekspos daftar array, Anda masih dapat memodifikasi daftar array. Anda tidak dapat mengatur daftar array yang berbeda untuk properti itu, tetapi Anda tidak bisa menghentikan pengguna dari mengubah daftar array.
Gishu
3
A constharus dikodekan dengan keras , di mana seperti yang readonlydapat diatur dalam konstruktor kelas.
Ada perbedaan penting antara bidang const dan readonly di C # .Net
const secara default statis dan perlu diinisialisasi dengan nilai konstan, yang tidak dapat dimodifikasi kemudian. Perubahan nilai juga tidak diizinkan dalam konstruktor. Itu tidak bisa digunakan dengan semua tipe data. Untuk ex-DateTime. Itu tidak bisa digunakan dengan tipe data DateTime.
readonly dapat dinyatakan sebagai statis, tetapi tidak perlu. Tidak perlu diinisialisasi pada saat deklarasi. Nilainya dapat ditetapkan atau diubah menggunakan konstruktor. Jadi, itu memberi keuntungan ketika digunakan sebagai anggota kelas contoh. Dua instansiasi yang berbeda mungkin memiliki nilai bidang baca hanya berbeda. Untuk mantan -
class A
{publicreadonlyintId;public A(int i){Id= i;}}
Kemudian bidang readonly dapat diinisialisasi dengan nilai spesifik instan, sebagai berikut:
A objOne =new A(5);
A objTwo =new A(10);
Di sini, instance objOne akan memiliki nilai bidang readonly sebagai 5 dan objTwo memiliki 10. Yang tidak mungkin menggunakan const.
Konstanta akan dikompilasi ke konsumen sebagai nilai literal sedangkan string statis akan berfungsi sebagai referensi ke nilai yang ditentukan.
Sebagai latihan, cobalah membuat perpustakaan eksternal dan mengkonsumsinya dalam aplikasi konsol, kemudian mengubah nilai-nilai di perpustakaan dan mengkompilasi ulang (tanpa mengkompilasi ulang program konsumen), letakkan DLL ke direktori dan jalankan EXE secara manual, Anda harus menemukan bahwa string konstan tidak berubah.
@Andrew Hare - ya, saya baru saja memeriksa. Saya sangat terkejut, itu adalah gotcha yang sebenarnya, saya benar-benar sangat terkejut dengan hal itu, kagum bahwa ini masalahnya ...!
ljs
Namun saya keberatan dengan penggunaan penunjuk kata di sini. Ini bukan pointer, itu referensi, dan ada adalah perbedaan di C # seperti yang Anda dapat memanipulasi pointer unmanaged dalam mode aman sehingga penting untuk membedakan antara keduanya.
ljs
2
Konstan
Kita perlu memberikan nilai ke bidang const ketika didefinisikan. Kompiler kemudian menyimpan nilai konstanta dalam metadata rakitan. Ini berarti bahwa konstanta hanya dapat didefinisikan untuk tipe primitif seperti boolean, char, byte, dan sebagainya. Konstanta selalu dianggap anggota statis, bukan anggota instan.
Hanya baca
Bidang yang hanya dapat dibaca hanya dapat diselesaikan saat runtime. Itu berarti kita bisa mendefinisikan nilai untuk nilai menggunakan konstruktor untuk tipe di mana bidang tersebut dinyatakan. Verifikasi dilakukan oleh kompiler yang bidang baca-nya tidak ditulis oleh metode apa pun selain konstruktor.
Konst dan readonly serupa, tetapi mereka tidak persis sama. Bidang const adalah konstanta waktu kompilasi, yang berarti bahwa nilai tersebut dapat dihitung pada waktu kompilasi. Bidang baca-saja memungkinkan skenario tambahan di mana beberapa kode harus dijalankan selama konstruksi jenis. Setelah konstruksi, bidang hanya baca tidak dapat diubah.
Misalnya, anggota const dapat digunakan untuk mendefinisikan anggota seperti:
karena nilai-nilai seperti 3.14 dan 0 adalah konstanta kompilasi-waktu. Namun, pertimbangkan kasus di mana Anda mendefinisikan suatu tipe dan ingin memberikan beberapa contoh pre-fab. Misalnya, Anda mungkin ingin mendefinisikan kelas Warna dan memberikan "konstanta" untuk warna umum seperti Hitam, Putih, dll. Tidak mungkin melakukan ini dengan anggota const, karena sisi kanan bukan konstanta waktu kompilasi. Orang dapat melakukan ini dengan anggota statis biasa:
publicclassColor{publicstaticColorBlack=newColor(0,0,0);publicstaticColorWhite=newColor(255,255,255);publicstaticColorRed=newColor(255,0,0);publicstaticColorGreen=newColor(0,255,0);publicstaticColorBlue=newColor(0,0,255);privatebyte red, green, blue;publicColor(byte r,byte g,byte b){
red = r;
green = g;
blue = b;}}
tapi kemudian tidak ada yang membuat klien Color tidak mau ikut campur, mungkin dengan menukar nilai Black and White. Tak perlu dikatakan, ini akan menimbulkan kekhawatiran bagi klien lain dari kelas Warna. Fitur "readonly" membahas skenario ini. Dengan hanya memperkenalkan kata kunci yang hanya bisa dibaca dalam deklarasi, kami menjaga inisialisasi yang fleksibel sambil mencegah kode klien dari mucking sekitar.
publicclassColor{publicstaticreadonlyColorBlack=newColor(0,0,0);publicstaticreadonlyColorWhite=newColor(255,255,255);publicstaticreadonlyColorRed=newColor(255,0,0);publicstaticreadonlyColorGreen=newColor(0,255,0);publicstaticreadonlyColorBlue=newColor(0,0,255);privatebyte red, green, blue;publicColor(byte r,byte g,byte b){
red = r;
green = g;
blue = b;}}
Sangat menarik untuk dicatat bahwa anggota const selalu statis, sedangkan anggota readonly bisa statis atau tidak, seperti bidang biasa.
Dimungkinkan untuk menggunakan kata kunci tunggal untuk kedua tujuan ini, tetapi ini mengarah ke masalah versi atau masalah kinerja. Asumsikan sejenak bahwa kami menggunakan satu kata kunci untuk ini (const) dan pengembang menulis:
publicclass A
{publicstaticconst C =0;}
dan pengembang lain menulis kode yang mengandalkan A:
publicclass B
{staticvoidMain(){Console.WriteLine(A.C);}}
Sekarang, dapatkah kode yang dihasilkan mengandalkan fakta bahwa AC adalah konstanta waktu kompilasi? Yaitu, bisakah penggunaan AC diganti dengan nilai 0? Jika Anda mengatakan "ya" untuk ini, maka itu berarti bahwa pengembang A tidak dapat mengubah cara AC diinisialisasi - ini mengikat tangan pengembang A tanpa izin. Jika Anda mengatakan "tidak" untuk pertanyaan ini, maka optimasi penting tidak terjawab. Mungkin penulis A yakin bahwa AC akan selalu nol. Penggunaan const dan readonly memungkinkan pengembang A untuk menentukan maksud. Ini membuat perilaku versi yang lebih baik dan juga kinerja yang lebih baik.
Perbedaannya adalah bahwa nilai bidang baca statis ditetapkan pada saat dijalankan, sehingga dapat memiliki nilai yang berbeda untuk eksekusi program yang berbeda. Namun, nilai bidang const diatur ke konstanta waktu kompilasi.
Ingat: Untuk jenis referensi, dalam kedua kasus (statis dan contoh), pengubah hanya baca mencegah Anda dari menetapkan referensi baru ke bidang. Itu secara khusus tidak membuat objek berubah ditunjuk oleh referensi.
Variabel konstan dideklarasikan dan diinisialisasi pada waktu kompilasi. Nilai tidak dapat diubah setelah bangsal. Variabel read-only akan diinisialisasi hanya dari konstruktor statis kelas. Hanya baca digunakan hanya ketika kita ingin menetapkan nilai pada waktu berjalan.
Definisi Anda tentang 'Hanya Baca' yang dapat diubah salah. Saya kira dengan 'ubah' Anda berarti 'set', seperti 'itu dapat diatur saat runtime'.
Ahmed
0
Satu hal yang menambah apa yang dikatakan orang di atas. Jika Anda memiliki majelis yang berisi nilai hanya baca (mis. ReadFly MaxFooCount = 4;), Anda dapat mengubah nilai yang dipanggil majelis panggilan dengan mengirimkan versi baru dari perakitan itu dengan nilai yang berbeda (mis. ReadFly MaxFooCount = 5;)
Tetapi dengan const, itu akan dilipat ke dalam kode penelepon ketika penelepon dikompilasi.
Jika Anda telah mencapai tingkat kemahiran C # ini, Anda siap untuk buku Bill Wagner, Efektif C #: 50 Cara Khusus untuk Meningkatkan C # Yang menjawab pertanyaan ini secara terperinci, (dan 49 hal lainnya).
Jawaban:
Terlepas dari perbedaan nyata
const
VSreadonly
dapat dihitung secara dinamis tetapi perlu ditugaskan sebelum konstruktor keluar .. setelah itu dibekukan.static
. Anda menggunakanClassName.ConstantName
notasi untuk mengaksesnya.Ada perbedaan yang halus. Pertimbangkan kelas yang didefinisikan dalam
AssemblyA
.AssemblyB
referensiAssemblyA
dan menggunakan nilai-nilai ini dalam kode. Ketika ini dikompilasi,const
nilai, itu seperti mencari-ganti, nilai 2 'dimasukkan ke dalamAssemblyB
' IL yang ada. Ini berarti bahwa jika besok saya akan memperbaruiI_CONST_VALUE
ke 20 di masa mendatang.AssemblyB
masih akan memiliki 2 sampai saya kompilasi ulang .readonly
nilai, itu sepertiref
ke lokasi memori. Nilai tidak dimasukkan keAssemblyB
IL. Ini berarti bahwa jika lokasi memori diperbarui,AssemblyB
dapatkan nilai baru tanpa kompilasi ulang. Jadi, jikaI_RO_VALUE
diperbarui ke 30, Anda hanya perlu membangunAssemblyA
. Semua klien tidak perlu dikompilasi ulang.Jadi, jika Anda yakin bahwa nilai konstanta tidak akan berubah, gunakan a
const
.Tetapi jika Anda memiliki konstanta yang dapat berubah (misalnya presisi) .. atau jika ragu, gunakan a
readonly
.Update: Aku perlu disebutkan karena dia menunjukkan ini dulu. Saya juga perlu menghubungkan di mana saya belajar ini .. Efektif C # - Bill Wagner
sumber
static
titik tampaknya menjadi titik paling penting dan berguna -consts are implicitly static
readonly
variabel dapat diubah di luar konstruktor (refleksi). Hanya kompiler yang mencoba menghalangi Anda untuk memodifikasi var di luar konstruktor.readonly
Variabel @ mini-me tidak diperbolehkan untuk diubah setelah konstruktor selesai, bahkan melalui refleksi. Runtime terjadi untuk tidak menegakkan ini. Runtime juga terjadi tidak untuk menegakkan bahwa Anda tidak mengubahstring.Empty
ke"Hello, world!"
, tapi aku masih tidak akan mengklaim bahwa ini membuatstring.Empty
dimodifikasi, atau kode yang tidak boleh berasumsi bahwastring.Empty
akan selalu menjadi nol-panjang string.Ada gotcha dengan const! Jika Anda mereferensikan konstanta dari rakitan lain, nilainya akan dikompilasi langsung ke rakitan panggilan. Dengan begitu ketika Anda memperbarui konstanta dalam rakitan yang direferensikan itu tidak akan berubah dalam rakitan panggilan!
sumber
Konstanta
Baca hanya bidang contoh
Bidang baca statis saja
sumber
Sekadar menambahkan, ReadOnly untuk tipe referensi hanya membuat referensi menjadi bukan nilai. Sebagai contoh:
sumber
string
yang bisa Anda gunakan sebagai konstanta?const
dengan tipe referensi selain string, tetapi konstanta hanya dapat memiliki nilainull
.Ini menjelaskannya . Ringkasan: const harus diinisialisasi pada waktu deklarasi, readonly dapat diinisialisasi pada konstruktor (dan dengan demikian memiliki nilai yang berbeda tergantung pada konstruktor yang digunakan).
EDIT: Lihat Gotcha Gishu di atas untuk perbedaan halus
sumber
const
: Tidak dapat diubah di mana pun.readonly
: Nilai ini hanya dapat diubah di konstruktor. Tidak dapat diubah dalam fungsi normal.sumber
Ada gotcha kecil dengan readonly. Bidang readonly dapat disetel beberapa kali dalam konstruktor. Sekalipun nilainya diatur dalam dua konstruktor berantai yang berbeda, ia tetap diizinkan.
sumber
Anggota konstan didefinisikan pada waktu kompilasi dan tidak dapat diubah pada saat runtime. Konstanta dinyatakan sebagai bidang, menggunakan
const
kata kunci dan harus diinisialisasi seperti yang dinyatakan.Seorang
readonly
anggota adalah seperti konstanta karena mewakili nilai yang tidak berubah. Perbedaannya adalah bahwareadonly
anggota dapat diinisialisasi pada saat runtime, dalam sebuah konstruktor, dan juga dapat diinisialisasi seperti yang dideklarasikan.const
static
(mereka statis secara implisit)dibaca saja
sumber
static const int i = 0;
const
deklarasi tidak bisa dibuat di dalam metode?Const adalah konstanta waktu kompilasi sedangkan readonly memungkinkan nilai untuk dihitung pada saat run-time dan ditetapkan dalam konstruktor atau penginisialisasi bidang. Jadi, 'const' selalu konstan tetapi 'readonly' adalah read-only setelah ditugaskan.
Eric Lippert dari tim C # memiliki informasi lebih lanjut tentang berbagai jenis ketidakberdayaan
sumber
Ini tautan lain menunjukkan bagaimana const tidak aman untuk versi, atau relevan untuk tipe referensi.
Ringkasan :
sumber
Hanya Baca : Nilai dapat diubah melalui Ctor saat runtime. Tetapi tidak melalui Fungsi anggota
Konstan : Dengan defult static. Nilai tidak dapat diubah dari mana saja (Ctor, Function, runtime dll no-where)
sumber
Gotcha lain: nilai readonly dapat diubah dengan kode "licik" melalui refleksi.
Dapatkah saya mengubah bidang yang diwarisi hanya baca pribadi di C # menggunakan refleksi?
sumber
Saya percaya
const
nilai adalah sama untuk semua objek (dan harus diinisialisasi dengan ekspresi literal), sedangkanreadonly
dapat berbeda untuk setiap instantiation ...sumber
Salah satu anggota tim di kantor kami memberikan panduan berikut tentang kapan harus menggunakan const, statis, dan hanya baca:
Satu catatan terakhir: bidang const adalah statis, tetapi kebalikannya tidak benar.
sumber
Keduanya konstan, tetapi const tersedia juga pada waktu kompilasi. Ini berarti bahwa salah satu aspek dari perbedaan adalah bahwa Anda dapat menggunakan variabel const sebagai input ke atribut constructor, tetapi tidak hanya variabel readonly.
Contoh:
sumber
kapan harus menggunakan
const
ataureadonly
const
readonly
App.config
, tetapi setelah diinisialisasi itu tidak dapat diubahsumber
Variabel bertanda const sedikit lebih banyak daripada makro #define yang diketik dengan kuat, pada waktu kompilasi variabel referensi const diganti dengan nilai literal sebaris. Sebagai akibatnya, hanya tipe nilai primitif bawaan tertentu yang dapat digunakan dengan cara ini. Variabel bertanda readonly dapat diatur, dalam konstruktor, pada saat run-time dan read-only-ness mereka diberlakukan selama run-time juga. Ada beberapa biaya kinerja kecil yang terkait dengan ini tetapi itu berarti Anda dapat menggunakan hanya baca dengan tipe apa pun (tipe referensi genap).
Juga, variabel const secara inheren statis, sedangkan variabel readonly dapat spesifik misalnya jika diinginkan.
sumber
CONST
Baca Saja
sumber
Gotcha lain .
Karena const benar-benar hanya bekerja dengan tipe data dasar, jika Anda ingin bekerja dengan kelas, Anda mungkin merasa "dipaksa" untuk menggunakan ReadOnly. Namun, waspadalah terhadap jebakan! ReadOnly berarti Anda tidak dapat mengganti objek dengan objek lain (Anda tidak dapat membuatnya merujuk ke objek lain). Tetapi setiap proses yang memiliki referensi ke objek bebas untuk mengubah nilai-nilai di dalam objek!
Jadi jangan bingung untuk berpikir bahwa ReadOnly menyiratkan pengguna tidak dapat mengubah hal-hal. Tidak ada sintaksis sederhana dalam C # untuk mencegah instantiasi suatu kelas agar nilai internalnya berubah (sejauh yang saya tahu).
sumber
A
const
harus dikodekan dengan keras , di mana seperti yangreadonly
dapat diatur dalam konstruktor kelas.sumber
Ada perbedaan penting antara bidang const dan readonly di C # .Net
const secara default statis dan perlu diinisialisasi dengan nilai konstan, yang tidak dapat dimodifikasi kemudian. Perubahan nilai juga tidak diizinkan dalam konstruktor. Itu tidak bisa digunakan dengan semua tipe data. Untuk ex-DateTime. Itu tidak bisa digunakan dengan tipe data DateTime.
readonly dapat dinyatakan sebagai statis, tetapi tidak perlu. Tidak perlu diinisialisasi pada saat deklarasi. Nilainya dapat ditetapkan atau diubah menggunakan konstruktor. Jadi, itu memberi keuntungan ketika digunakan sebagai anggota kelas contoh. Dua instansiasi yang berbeda mungkin memiliki nilai bidang baca hanya berbeda. Untuk mantan -
Kemudian bidang readonly dapat diinisialisasi dengan nilai spesifik instan, sebagai berikut:
Di sini, instance objOne akan memiliki nilai bidang readonly sebagai 5 dan objTwo memiliki 10. Yang tidak mungkin menggunakan const.
sumber
Konstanta akan dikompilasi ke konsumen sebagai nilai literal sedangkan string statis akan berfungsi sebagai referensi ke nilai yang ditentukan.
Sebagai latihan, cobalah membuat perpustakaan eksternal dan mengkonsumsinya dalam aplikasi konsol, kemudian mengubah nilai-nilai di perpustakaan dan mengkompilasi ulang (tanpa mengkompilasi ulang program konsumen), letakkan DLL ke direktori dan jalankan EXE secara manual, Anda harus menemukan bahwa string konstan tidak berubah.
sumber
Konstan
Kita perlu memberikan nilai ke bidang const ketika didefinisikan. Kompiler kemudian menyimpan nilai konstanta dalam metadata rakitan. Ini berarti bahwa konstanta hanya dapat didefinisikan untuk tipe primitif seperti boolean, char, byte, dan sebagainya. Konstanta selalu dianggap anggota statis, bukan anggota instan.
Hanya baca
Bidang yang hanya dapat dibaca hanya dapat diselesaikan saat runtime. Itu berarti kita bisa mendefinisikan nilai untuk nilai menggunakan konstruktor untuk tipe di mana bidang tersebut dinyatakan. Verifikasi dilakukan oleh kompiler yang bidang baca-nya tidak ditulis oleh metode apa pun selain konstruktor.
Lebih jauh tentang keduanya dijelaskan di sini di artikel ini
sumber
Terutama; Anda dapat menetapkan nilai ke bidang readonly statis ke nilai non-konstan saat runtime, sedangkan const harus diberi nilai konstan.
sumber
Konst dan readonly serupa, tetapi mereka tidak persis sama. Bidang const adalah konstanta waktu kompilasi, yang berarti bahwa nilai tersebut dapat dihitung pada waktu kompilasi. Bidang baca-saja memungkinkan skenario tambahan di mana beberapa kode harus dijalankan selama konstruksi jenis. Setelah konstruksi, bidang hanya baca tidak dapat diubah.
Misalnya, anggota const dapat digunakan untuk mendefinisikan anggota seperti:
karena nilai-nilai seperti 3.14 dan 0 adalah konstanta kompilasi-waktu. Namun, pertimbangkan kasus di mana Anda mendefinisikan suatu tipe dan ingin memberikan beberapa contoh pre-fab. Misalnya, Anda mungkin ingin mendefinisikan kelas Warna dan memberikan "konstanta" untuk warna umum seperti Hitam, Putih, dll. Tidak mungkin melakukan ini dengan anggota const, karena sisi kanan bukan konstanta waktu kompilasi. Orang dapat melakukan ini dengan anggota statis biasa:
tapi kemudian tidak ada yang membuat klien Color tidak mau ikut campur, mungkin dengan menukar nilai Black and White. Tak perlu dikatakan, ini akan menimbulkan kekhawatiran bagi klien lain dari kelas Warna. Fitur "readonly" membahas skenario ini. Dengan hanya memperkenalkan kata kunci yang hanya bisa dibaca dalam deklarasi, kami menjaga inisialisasi yang fleksibel sambil mencegah kode klien dari mucking sekitar.
Sangat menarik untuk dicatat bahwa anggota const selalu statis, sedangkan anggota readonly bisa statis atau tidak, seperti bidang biasa.
Dimungkinkan untuk menggunakan kata kunci tunggal untuk kedua tujuan ini, tetapi ini mengarah ke masalah versi atau masalah kinerja. Asumsikan sejenak bahwa kami menggunakan satu kata kunci untuk ini (const) dan pengembang menulis:
dan pengembang lain menulis kode yang mengandalkan A:
Sekarang, dapatkah kode yang dihasilkan mengandalkan fakta bahwa AC adalah konstanta waktu kompilasi? Yaitu, bisakah penggunaan AC diganti dengan nilai 0? Jika Anda mengatakan "ya" untuk ini, maka itu berarti bahwa pengembang A tidak dapat mengubah cara AC diinisialisasi - ini mengikat tangan pengembang A tanpa izin. Jika Anda mengatakan "tidak" untuk pertanyaan ini, maka optimasi penting tidak terjawab. Mungkin penulis A yakin bahwa AC akan selalu nol. Penggunaan const dan readonly memungkinkan pengembang A untuk menentukan maksud. Ini membuat perilaku versi yang lebih baik dan juga kinerja yang lebih baik.
sumber
Hanya Baca: Nilai akan diinisialisasi hanya sekali dari konstruktor kelas.
const: dapat diinisialisasi dalam fungsi apa pun tetapi hanya sekali
sumber
Perbedaannya adalah bahwa nilai bidang baca statis ditetapkan pada saat dijalankan, sehingga dapat memiliki nilai yang berbeda untuk eksekusi program yang berbeda. Namun, nilai bidang const diatur ke konstanta waktu kompilasi.
Ingat: Untuk jenis referensi, dalam kedua kasus (statis dan contoh), pengubah hanya baca mencegah Anda dari menetapkan referensi baru ke bidang. Itu secara khusus tidak membuat objek berubah ditunjuk oleh referensi.
Untuk detail, silakan merujuk ke C # Pertanyaan yang Sering Diajukan tentang topik ini: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
sumber
Variabel konstan dideklarasikan dan diinisialisasi pada waktu kompilasi. Nilai tidak dapat diubah setelah bangsal. Variabel read-only akan diinisialisasi hanya dari konstruktor statis kelas. Hanya baca digunakan hanya ketika kita ingin menetapkan nilai pada waktu berjalan.
sumber
Const : Nilai konstan absolut selama masa hidup aplikasi.
Hanya Baca : Dapat diubah dalam waktu berjalan.
sumber
Satu hal yang menambah apa yang dikatakan orang di atas. Jika Anda memiliki majelis yang berisi nilai hanya baca (mis. ReadFly MaxFooCount = 4;), Anda dapat mengubah nilai yang dipanggil majelis panggilan dengan mengirimkan versi baru dari perakitan itu dengan nilai yang berbeda (mis. ReadFly MaxFooCount = 5;)
Tetapi dengan const, itu akan dilipat ke dalam kode penelepon ketika penelepon dikompilasi.
Jika Anda telah mencapai tingkat kemahiran C # ini, Anda siap untuk buku Bill Wagner, Efektif C #: 50 Cara Khusus untuk Meningkatkan C # Yang menjawab pertanyaan ini secara terperinci, (dan 49 hal lainnya).
sumber