Statik salt okunur ve sabit


1386

Etrafı constve static readonlyalanları okudum . Sadece sabit değerler içeren bazı sınıflarımız var. Sistemimizdeki çeşitli şeyler için kullanılır. Bu yüzden gözlemimin doğru olup olmadığını merak ediyorum:

Bu tür sabit değerler her zaman static readonlyherkese açık olan her şey için mi olmalı ? Ve sadece constdahili / korumalı / özel değerler için mi kullanılır?

Ne önerirsiniz? Hatta static readonlyalanları kullanmamalı , daha çok özellikleri kullanmalı mıyım?


5
İşte benim lehime bulduğum çok ilginç bir tek durum static readonly: İçinde IEnumeratorbir kontrol edilemeyen tetikleyecek bir const kullanmayı deneyin yieldve korkunç bir "Dahili derleyici hatası" alırsınız . Unity3D dışında kodu test etmedim, ama bu bir mono veya .NET hatası olduğuna inanıyorum . Yine de bir c # sorun.
cregox


8
başka bir fark, bir anahtarda bir const dize kullanabilirsiniz, ancak statik bir salt okunur dize
kullanamazsınız

7
static readonlyswitch-caseifadede casedeğişken olarak kullanılamaz, constbu amaçla gereklidir.
Mostafiz Rahman

3
static readonlyözellik parametresi olarak da kullanılamaz
Dread Boy

Yanıtlar:


940

public static readonlyalanlar biraz sıradışı; public staticözellikler (yalnızca a ile get) daha yaygın olur (belki bir private static readonlyalan tarafından desteklenir ).

constdeğerler doğrudan çağrı sitesine yakılır; bu çift kenarlı:

  • değerin çalışma zamanında, belki de config'ten getirilmesi işe yaramaz.
  • bir const değerini değiştirirseniz, tüm istemcileri yeniden oluşturmanız gerekir
  • ancak bir yöntem çağrısından kaçındığı için daha hızlı olabilir ...
  • ... bazen JIT tarafından satır içine alınmış olabilir.

Değer asla değişmezse, const iyidir - Zerovb makul consts yapın; p Bunun dışında staticözellikler daha yaygındır.


13
Neden bir alanın üzerinde bir mülk? Eğer değişmez bir sınıfsa, hiçbir fark görmüyorum.
Michael Hedgpeth

73
@Michael - her zamanki gibi aynı nedenler; uygulamayı gizler. (Daha sonra) tembel yüklü, konfigürasyon tabanlı, bir cephe veya herhangi bir şey olması gerektiğini bulabilirsiniz. Gerçekte, ya genellikle iyi olur ...
Marc Gravell

42
@CoffeeAddict tanımına göre, sabit bir yapılandırma dosyasından değer çekmiyor ; derleme zamanında bir literal olarak yakılır. Bir sabiti çalışma zamanında kullanabilmenin tek yolu alanların yansımasıdır. Başka zaman sen, derleyici bunu kullanmayı deneyin zaten olarak sizin ikame sabit için kullanımını değişmez kullanım; yani kodunuzdaki bir yöntem 6 sabit kullanıyorsa ve bunu IL olarak incelerseniz, sürekli aramalardan söz edilmeyecektir; değişmez değerler basitçe yerinde yüklenecektir
Marc Gravell

37
@MarcGravell - DİKKAT: readonlyalanlar anahtar / büyük / küçük harf ifadelerinde kullanılamaz, bunun yerine bunlara ihtiyacınız vardır const.
Luciano

7
@didibus Bir alanı bir mülkle değiştirmek aslında API'yi bozar. C # 'daki bir alan bir değişken gibi etkili bir şekilde hareket ederken, C #' daki bir özellik bir alıcı yöntemi ve / veya bir ayarlayıcı yöntemi yazmak için bir sözdizimi yardımcısıdır. Bu fark diğer montajlar söz konusu olduğunda önemlidir. Bir alanı bir özelliğe değiştirirseniz ve bu alana bağlı olan diğer derlemeler varsa, bu diğer derlemelerin yeniden derlenmesi gerekir.
Stephen Booher

237

Ben kullanırım static readonlyeğer Tüketici farklı bir derlemede olduğunu. constVe Tüketiciyi iki farklı meclise sahip olmak, kendinizi ayağınızdan vurmanın güzel bir yoludur .


5
Bu yüzden bazılarının bahsettiği veya bahsettiği gibi, sadece kamuya açık hale getirilmişlerse aslında iyi bilinen sabitler için değerler kullanmak akıllıca olabilir, aksi takdirde dahili, korumalı veya özel erişim kapsamı için ayrılmalıdır.
jpierson

1
@Dio Hâlâ mevcut olmasının nedeni, kendi başına bir sorun olmamasıdır - bunun farkında olunması gereken bir şeydir, ancak montaj sınırları boyunca sabitleri satır içine alma yeteneği performans için iyi bir şeydir. Gerçekten sadece "sabit" in "asla değişmeyeceği" anlamına geldiği anlaşılıyor.
Michael Stum

1
@MichaelStum Tamam "Sorun" dememeliyim. Çalışma hattımda, const var ve bunu meclisler arasında paylaşıyorum, ancak her dağıtım veya kod gönderimi için yeniden derliyorum. Bununla birlikte, bu gerçek kesinlikle dikkate almaya değer.
Dio Phung

1
Yani, genel olarak internal constveya public static readonlyistenen görünüme bağlı olarak.
Iiridayn

2
@Iiridayn Evet, bu ona bakmak için kötü bir yol değil. Dikkate alınması gereken birkaç kenar durum vardır (örneğin, Yansıma kullanıyorsanız veya bir öznitelikte bir değere ihtiyaç duyuluyorsa) ve geçerli kullanımları vardır public const(örneğin, bir standardın herhangi bir parçası. XML ile çalıştığımda, ad alanları bir demet ile dosyalanır public const string.) Ancak genel olarak, public constyalnızca sonuçları doğru bir şekilde değerlendirdikten sonra kullanılmalıdır.
Michael Stum


176

Bu sadece diğer cevaplara bir ektir. Onları tekrarlamayacağım (şimdi dört yıl sonra).

A constve const olmayanların farklı semantiklere sahip olduğu durumlar vardır . Örneğin:

const int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

çıktısını Truealırken:

static readonly int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

yazar False.

Nedeni yöntem ki x.Equalsikisi alır aşırı yükleri, birine sahiptir short( System.Int16bir alan) ve bir object( System.Object). Şimdi soru, bir veya her ikisinin benim yargümanımla geçerli olup olmadığıdır .

Tüm y(hazır) bir derleme zaman sabitidir, constdurum, orada örtülü bir dönüşüm var olduğu önemli hale gelen int kadar short olması koşuluyla int, bir sabittir ve şu koşulla ki değeri bir aralığında, C # derleyicisi doğrular short( ki 42). Bkz . C # Dil Spesifikasyonu'ndaki Örtülü sabit ifade dönüşümleri . Bu nedenle her iki aşırı yük de dikkate alınmalıdır. Aşırı yük Equals(short)(herhangi bir tercih edilen shortbir olduğunu object, ama hepsi değil objectvardır short). Böylece ydönüştürülür shortve aşırı yük kullanılır. Sonra aynı değerden Equalsikisini karşılaştırır shortve bu verir true.

Ne zaman ybir sabit değildir, herhangi bir kapalı dönüşüm intiçin shortmevcuttur. Çünkü genel olarak an int, a'ya sığmayacak kadar büyük olabilir short. ( Açık bir dönüşüm var, ama söylemedim Equals((short)y), bu alakalı değil.) Sadece bir aşırı yükün geçerli olduğunu görüyoruz Equals(object). Böylece ykutulu object. Sonra Equalsbir karşılaştırma için gidiyor System.Int16bir etmek System.Int32ve çalışma zamanı türleri bile kabul etmiyorum çünkü o verecektir false.

Bazı (nadir) durumlarda, bir consttür üyesini bir static readonlyalana (veya mümkün olduğunda başka bir yolla) değiştirmenin programın davranışını değiştirebileceği sonucuna vardık .


17
Kabul edilen cevaba iyi bir katkı. Veri türlerinin ve diğer benzer yönergelerin (deneme yakalamaları vb. Gibi) uygun bir şekilde dönüştürülmesinin deneyimli programcıların bir zımbası olması ve derleyiciye bırakılmaması gerektiğini eklemek istiyorum. Yine de buradan yeni bir şey öğrendim. Teşekkür ederim.
Uknight

Vay canına, C # 'da uzun zamandır programlama yapıyordum ve kısa menzil içindeki bir const int'in dolaylı olarak kısaca dönüştürülebileceğini asla tahmin edemezdim. Bunun garip olduğunu söylemeliyim. Ben C # seviyorum ama çok değer katmak görünmüyor ama sürekli düşünmek için gerekli beyin gücü çok eklemek bu garip tutarsızlıklar, özellikle yeni başlayanlar için can sıkıcı olabilir.
Mike Marynowski

@MikeMarynowski Yeterince doğru. Ancak, ifadeyi short x = 42;yasal hale getirmek için bu kuralı (diğer nedenlerin yanı sıra) yaptıklarını düşünüyorum . Çünkü orada dolaylı olarak intdeğişmez bir değişmez var . Ama sonra bunu sadece sayısal değişmezlerle kısıtlamış olabilirler; ancak, nerede olarak tanımlandığı gibi şeylere de izin vermeyi seçtiler ve bununla sonuçlandı. 42short xshort x = y;yconst int y = 42;
Jeppe Stig Nielsen

88

Dikkat edilmesi gereken bir şey const , ilkel / değer türleriyle sınırlıdır (istisna dizelerdir)


30
Aslında constnull olarak başlatılması dışında, diğer türler için de kullanılabilir, bu da işe yaramaz hale getirir :)
nawfal

6
istisna olarak System.Exception? :)
Memet Olsen

4
Daha kesin olarak @nawfal, tek bir değer türleri için constde kullanılabilir, olan sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, artı herhangi bir enumtür. constgibi başka değer türleri için kullanılamaz DateTimeveya TimeSpanya BigInteger. Ayrıca IntPtryapı için kullanılamaz (bazıları tarafından "ilkel" bir tip olarak kabul edilir; ilkel tip terimi C # 'da kafa karıştırıcıdır). Reference constTüm referans tipleri için kullanılabilir . Tür ise string, herhangi bir dize değeri belirtilebilir. Aksi takdirde, değer olmalıdır null.
Jeppe Stig Nielsen

@JeppeStigNielsen - Son zamanlarda bu konuda servy ile bir tartışma yaptım - o kullanarak bir şey (değer ve referans türleri) yapabileceğinizi belirtti . İçin türleri, varsayılan değerlere ayarlanmış tüm üyeleri ile bir örnek bu. constdefaultstruct
Wai Ha Lee

28

Statik Salt Okunur : Değer static, çalışma zamanında kurucu aracılığıyla değiştirilebilir . Ancak üye Fonksiyon aracılığıyla değil.

Sabit : Varsayılan olarak static. Değer herhangi bir yerden değiştirilemez (Ctor, Function, runtime vs. no-where).

Salt Okunur : Değer, çalışma zamanında kurucu aracılığıyla değiştirilebilir. Ancak üye Fonksiyon aracılığıyla değil.

Benim repo: C # özellik türleri bir göz atabilirsiniz .


1
Kötü haber ... kopuk bağlantı!
Fer R


İyi snippet'ler Siam ভাই :)
Muhammad Ashikuzzaman

25

readonlyAnahtar kelime farklıdır constanahtar kelime. Bir constalan yalnızca alanın beyanında başlatılabilir. Bir readonlyalan ya bildirimde ya da bir kurucuda başlatılabilir. Bu nedenle, readonlykullanılan yapıcıya bağlı olarak alanlar farklı değerlere sahip olabilir. Ayrıca, bir constalan derleme zamanı sabiti olsa da, readonlyalan çalışma zamanı sabitleri için kullanılabilir

Kısa ve net MSDN referansı burada


16

constve readonlybenzerdir, ancak tam olarak aynı değildirler.

Bir constalan derleme zamanı sabitidir, yani bu değer derleme zamanında hesaplanabilir. Bir readonlyalan bazı kod tipi inşaatı sırasında çalıştırılmalıdır hangi ek senaryolar sağlar. İnşaattan sonra bir readonlyalan değiştirilemez.

Örneğin, constüyeler aşağıdaki gibi üyeleri tanımlamak için kullanılabilir:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

3.14 ve 0 gibi değerler derleme zamanı sabitleridir. Ancak, bir tür tanımladığınız ve bu türün bazı fab öncesi örneklerini sağlamak istediğiniz durumu göz önünde bulundurun. Örneğin, bir Color sınıfı tanımlamak ve Siyah, Beyaz vb. Ortak renkler için "sabitler" sağlamak isteyebilirsiniz. Sağ taraflar derleme zamanı sabitleri olmadığından bunu const üyeleriyle yapmak mümkün değildir. Bunu düzenli statik üyelerle yapabiliriz:

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, green, blue) = (r, g, b);
}

Ama sonra, bir Renk müşterisinin, belki de Siyah ve Beyaz değerlerini değiştirerek, onunla karışmasını engelleyecek hiçbir şey yoktur. Söylemeye gerek yok, bu, Color sınıfının diğer istemcileri için şaşkınlığa neden olur. "Salt okunur" özellik bu senaryoyu ele alır.

readonlyAnahtar kelimeyi yalnızca bildirimlere ekleyerek, istemci kodunun karışmasını önlerken esnek başlatmayı koruruz.

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, green, blue) = (r, g, b);
}

Const üyelerinin her zaman statik olduğunu, ancak salt okunur bir üyenin normal bir alan gibi statik olabileceğini veya olmayabileceğini belirtmek ilginçtir.

Bu iki amaç için tek bir anahtar kelime kullanmak mümkündür, ancak bu sürüm oluşturma sorunlarına veya performans sorunlarına yol açar. Bir an için bunun için (const) tek bir anahtar kelime kullandığımızı ve bir geliştiricinin şunu yazdığını varsayın:

public class A
{
    public static const C = 0;
}

ve farklı bir geliştirici A'ya dayanan bir kod yazdı:

public class B
{
    static void Main() => Console.WriteLine(A.C);
}

Şimdi, oluşturulan kod AC'nin derleme zamanı sabiti olmasına güvenebilir mi? Yani, AC kullanımı sadece 0 değeri ile değiştirilebilir mi? Buna "evet" derseniz, A geliştiricisinin AC'nin başlatılma şeklini değiştiremeyeceği anlamına gelir - bu, A geliştiricisinin ellerini izinsiz bağlar.

Bu soruya "hayır" derseniz, önemli bir optimizasyon kaçırılır. Belki de A'nın yazarı AC'nin her zaman sıfır olacağı konusunda olumludur. Hem const hem de salt okunur kullanımı, A geliştiricisinin amacı belirtmesine izin verir. Bu, daha iyi sürüm oluşturma davranışı ve daha iyi performans sağlar.


12

Benim tercihim, mümkün olduğu kadar const kullanmaktır , bu da yukarıda belirtildiği gibi değişmez ifadelerle veya değerlendirme gerektirmeyen bir şeyle sınırlıdır.

Eğer bu sınırlamaya karşı koyarsam, o zaman bir uyarı ile statik olarak salt okunur olurum . Ben genellikle gaz giderici bir kamu statik özelliği ve destek kullanacağı özel statik salt okunur Marc bahseder gibi sahadan burada .


7

Const: Const "sabit" ten başka bir şey değildir, değeri sabit olan ancak derleme zamanında değişkendir. Ve buna bir değer atamak zorunludur. Varsayılan olarak bir sabit statiktir ve tüm program boyunca bir sabit değişkenin değerini değiştiremeyiz.

Statik ReadOnly: Statik Readonly tipi bir değişkenin değeri çalışma zamanında atanabilir veya derleme zamanında atanabilir ve çalışma zamanında değiştirilebilir. Ancak bu değişkenin değeri yalnızca statik yapıcıda değiştirilebilir. Ve daha fazla değiştirilemez. Çalışma zamanında yalnızca bir kez değişebilir

Referans: c-sharpcorner


6

Statik bir salt okunur alan, daha sonraki bir versiyonda değişebilecek bir değer diğer montajlara maruz bırakıldığında avantajlıdır.

Örneğin, montajın Xaşağıdaki gibi bir sabit oluşturduğunu varsayalım :

public const decimal ProgramVersion = 2.3;

Montaj bu sabiti Yreferans Xalıp kullanırsa, 2.3 değeri Yderlendiğinde montajda pişirilir . Bu X, daha sonra 2.4 olarak ayarlanan sabitle yeniden derlenirse, yeniden derleninceye Ykadar eski 2.3 değerini kullanacağı anlamına gelir Y. Statik bir salt okunur alan bu sorunu önler.

Buna bakmanın bir başka yolu, gelecekte değişebilecek herhangi bir değerin tanım gereği sabit olmaması ve dolayısıyla bir olarak temsil edilmemesi gerektiğidir.


3

const:

  1. değer beyan üzerine verilmelidir
  2. zaman sabiti derleme

Sadece oku:

  1. değeri bildirim üzerine veya kurucuları kullanarak çalışma zamanı sırasında verilebilir. Değer, kullanılan kurucuya bağlı olarak değişebilir.
  2. çalışma süresi sabiti

3

Const : const değişken değerleri, bildirimle birlikte tanımlanmalıdır ve bundan sonra değişmez. const dolaylı olarak statiktir, bu nedenle sınıf örneği oluşturmadan bunlara erişebiliriz. bunun derleme zamanında bir değeri vardır

ReadOnly : Çalışma sırasında yapıcıyı kullanmanın yanı sıra bildirirken tanımlayabileceğimiz salt okunur değişken değerler. salt okunur değişkenler sınıf örneği olmadan erişemez.

Statik salt okunur : yalnızca statik kurucu aracılığıyla değil, aynı zamanda başka bir kurucu ile değil, beyan ederken tanımlayabileceğimiz statik salt okunur değişken değerleri. Bu değişkenler ayrıca sınıf örneği oluşturmadan da erişebiliriz (statik değişkenler olarak).

Değişkenleri farklı montajlarda tüketmemiz gerekiyorsa statik salt okunur daha iyi bir seçim olacaktır.Lütfen aşağıdaki bağlantıdaki tüm ayrıntıları kontrol edin

https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/


Bana cevabı neden düşürdüğünü söyleyebilir misin, bu yüzden kendimi burada da güncelleyebilirim.
user1756922

DV değil, ancak bu cevabın burada zaten kapsamlı olan cevaplara gerçekten bir şey eklememesi olabilir.
Marc L.

Gerçekten de, 90'ların sonlarında Java'da, birlikte çalıştığımız (birbirine referans verilen) sınıf dosyaları ve ortak const dizesi ile kopyalandıkları için farklı kavanozlar üreten çok sayıda insanı yaşadığımızı
hatırlayın

2

C # .Net'te const ve statik salt okunur alanlar arasında küçük bir fark vardır.

const derleme zamanında değerle başlatılmalıdır.

const varsayılan olarak statiktir ve daha sonra değiştirilemeyen sabit değerle başlatılması gerekir. Tüm veri tipleriyle kullanılamaz. Ex DateTime için. DateTime veri tipiyle kullanılamaz.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public static readonly string Name = string.Empty; //No error, legal

salt okunur olarak statik olarak bildirilebilir, ancak gerekli değildir. Beyan sırasında başlatmaya gerek yoktur. Değeri bir kez yapıcı kullanılarak atanabilir veya değiştirilebilir. Dolayısıyla, salt okunur alanın değerini bir kez değiştirme olasılığı vardır (statik olup olmadığı önemli değildir), const ile mümkün değildir.


0

Sabitler adın ima ettiği gibidir, değişmeyen alanlar ve genellikle kodda derleme zamanında statik olarak tanımlanır.

Salt okunur değişkenler belirli koşullar altında değişebilen alanlardır.

Bunları sabit olarak ilk kez bildirdiğinizde başlatılabilirler, ancak genellikle yapıcı içindeki nesne yapımı sırasında başlatılırlar.

Başlatma işlemi gerçekleştirildikten sonra, yukarıda belirtilen koşullarda değiştirilemezler.

Statik salt okunur benim için kötü bir seçim gibi geliyor, çünkü eğer statik ve asla değişmezse, sadece genel const kullanın, eğer değişebilirse sabit değildir ve sonra ihtiyaçlarınıza bağlı olarak, ya okuma -sadece veya sadece düzenli bir değişken.

Ayrıca, bir başka önemli ayrım, bir sabitin sınıfa ait olması ve salt okunur değişkenin örneğe ait olmasıdır!


0

Bir const (derleme zamanında belirlenir), switch deyimlerinde veya öznitelik yapıcılarında olduğu gibi salt okunur bir statikin yapılamadığı durumlarda kullanılabilir. Bunun nedeni, salt okunur alanların yalnızca çalışma zamanında çözümlenmesidir ve bazı kod yapıları derleme zamanı güvencesi gerektirir. Bir salt okunur statik, genellikle gerekli ve yararlı bir şey olan bir yapıcıda hesaplanabilir. Fark, benim görüşüme göre kullanımları gibi işlevseldir.

Bellek ayırma açısından, en azından dizelerle (bir referans türü), her ikisinin de stajyer olması ve tek bir interned örneğine başvurması açısından bir fark yoktur.

Şahsen, benim varsayılanım salt okunurdur, çünkü benim için daha anlamsal ve mantıklı bir anlam ifade eder, özellikle de derleme zamanında çoğu değere ihtiyaç duyulmadığından. Ve bu arada, kamuya açık salt okunur statüler, işaretli cevap durumlarının olağan dışı veya nadir değildir: örneğin, System.String.Emptybirdir.


0

Sabit ve statik salt okunur bildirme arasındaki bir diğer fark bellek ayırmadadır.

Statik alan , o türün bir örneğinden ziyade bir nesnenin türüne aittir . Sonuç olarak, sınıfa ilk kez atıfta bulunulduktan sonra, statik alan geri kalan süre boyunca bellekte "yaşar" ve statik alanın aynı örneğine türün tüm örnekleri tarafından başvuru yapılır.

Öte yandan, bir const alanı "türünün bir örneğine aittir.

Ayırma belleği sizin için daha önemliyse, const kullanmayı tercih edin . Hız ise, statik olarak salt okunur kullanın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.