Apa perbedaan antara const
dan readonly
di C #?
Kapan Anda akan menggunakan satu di atas yang lain?
Apa perbedaan antara const
dan readonly
di C #?
Kapan Anda akan menggunakan satu di atas yang lain?
Jawaban:
Terlepas dari perbedaan nyata
const
VS readonly
dapat dihitung secara dinamis tetapi perlu ditugaskan sebelum konstruktor keluar .. setelah itu dibekukan.static
. Anda menggunakan ClassName.ConstantName
notasi untuk mengaksesnya.Ada perbedaan yang halus. Pertimbangkan kelas yang didefinisikan dalam AssemblyA
.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
referensi AssemblyA
dan menggunakan nilai-nilai ini dalam kode. Ketika ini dikompilasi,
const
nilai, itu seperti mencari-ganti, nilai 2 'dimasukkan ke dalam AssemblyB
' IL yang ada. Ini berarti bahwa jika besok saya akan memperbarui I_CONST_VALUE
ke 20 di masa mendatang. AssemblyB
masih akan memiliki 2 sampai saya kompilasi ulang .readonly
nilai, itu seperti ref
ke lokasi memori. Nilai tidak dimasukkan ke AssemblyB
IL. Ini berarti bahwa jika lokasi memori diperbarui, AssemblyB
dapatkan nilai baru tanpa kompilasi ulang. Jadi, jika I_RO_VALUE
diperbarui 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
.
public const int CM_IN_A_METER = 100;
Tetapi jika Anda memiliki konstanta yang dapat berubah (misalnya presisi) .. atau jika ragu, gunakan a readonly
.
public readonly float 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
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 mengubah string.Empty
ke "Hello, world!"
, tapi aku masih tidak akan mengklaim bahwa ini membuat string.Empty
dimodifikasi, atau kode yang tidak boleh berasumsi bahwa string.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!
Sekadar menambahkan, ReadOnly untuk tipe referensi hanya membuat referensi menjadi bukan nilai. Sebagai contoh:
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
string
yang bisa Anda gunakan sebagai konstanta?
const
dengan tipe referensi selain string, tetapi konstanta hanya dapat memiliki nilai null
.
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.
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : 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 const
kata kunci dan harus diinisialisasi seperti yang dinyatakan.
public class MyClass
{
public const double PI1 = 3.14159;
}
Seorang readonly
anggota adalah seperti konstanta karena mewakili nilai yang tidak berubah. Perbedaannya adalah bahwa readonly
anggota dapat diinisialisasi pada saat runtime, dalam sebuah konstruktor, dan juga dapat diinisialisasi seperti yang dideklarasikan.
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
const
static
(mereka statis secara implisit)dibaca saja
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
Ini tautan lain menunjukkan bagaimana const tidak aman untuk versi, atau relevan untuk tipe referensi.
Ringkasan :
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)
Gotcha lain: nilai readonly dapat diubah dengan kode "licik" melalui refleksi.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
Dapatkah saya mengubah bidang yang diwarisi hanya baca pribadi di C # menggunakan refleksi?
Saya percaya const
nilai adalah sama untuk semua objek (dan harus diinisialisasi dengan ekspresi literal), sedangkan readonly
dapat berbeda untuk setiap instantiation ...
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.
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:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
kapan harus menggunakan const
ataureadonly
const
readonly
App.config
, tetapi setelah diinisialisasi itu tidak dapat diubahVariabel 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.
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).
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.
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
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
{
public readonly int Id;
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.
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
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:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
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:
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(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.
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(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:
public class A
{
public static const C = 0;
}
dan pengembang lain menulis kode yang mengandalkan A:
public class B
{
static void Main() {
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.
Untuk detail, silakan merujuk ke C # Pertanyaan yang Sering Diajukan tentang topik ini: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
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.
Const : Nilai konstan absolut selama masa hidup aplikasi.
Hanya Baca : Dapat diubah dalam waktu berjalan.
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).