Neden String.Empty sabit değil?


188

.Net'te String.Empty neden bir sabit yerine salt okunur? Sadece bu kararın ardındaki mantığın ne olduğunu bilen biri olup olmadığını merak ediyorum.


5
Bu soru bunu çözebilir, kısa cevap, kimse bilmiyor ...
gdoron Monica

Evet, Eric Lippert yanıtı için +1, teşekkürler!
travis

Özellikle Decimal.Zero'nun const olduğu göz önüne alındığında (kullanıcı bakış açısından ...)
Hamish Grubijan

Yanıtlar:


148

Bunun static readonlyyerine kullanılmasının nedeni, constMicrosoft'un burada Paylaşılan Kaynak Ortak Dil Altyapısı 2.0 Sürümünde belirttiği gibi yönetilmeyen kodla kullanılmasıdır . Bakılacak dosya sscli20\clr\src\bcl\system\string.cs.

Empty sabiti boş dize değerini tutar. Derleyicinin bunu değişmez olarak işaretlememesi için String yapıcısını çağırmamız gerekir.

Bunu değişmez olarak işaretlemek, yerelden erişebileceğimiz bir alan olarak görünmemesi anlamına gelir.

Bu bilgileri CodeProject bu kullanışlı makaleden buldum .


Bu yorumu açıklayabilirseniz gerçekten sevinirim (çünkü Jon Skeet yapamadı ...) buraya bakın: stackoverflow.com/questions/8462697/…
gdoron,

2
@gdoron: Benim tahminim (ve bir tahmin) bu. Bir değer değişmez değer (sabit) olarak tanımlandığında, değerine başvurulduğu yerlere eklenirken, değişmez değer olarak tanımlanmadığında değerin kaynağına başvurulur ve çalışma zamanında gerçek değer alınır. İkincisinin çalışma zamanında yerel ve .NET arasında dizenin düzgün bir şekilde hizalanmasını sağlayabileceğinden şüpheleniyorum - eğer bir değişmez olsaydı, belki de yerel derleyici bir şekilde değişmez değeri kendi yerel koduna çekmelidir. mümkün. Bütün bunlar benim düşünceme göre.
Jeff Yates

7
Bu yöntemlerde varsayılan parametre değerleri için string.Empty yerine "" kullanmak zorunda olduğu anlamına gelir. Bu biraz sinir bozucu.
nicodemus13

17
"" bir hata gibi görünebilir, dize.Empty kasıtlı bir niyet gösterir
Christopher Stevenson

3
@JeffYates Ben tutarlı olmadığını gerçeği zaten can sıkıcı olduğunu eklemek istiyorum. İnsanlar kodun geri kalanını görür ve "String.Empty yerine burada neden" "kullanıyor" diye merak ederdi. Ciddi olarak String.Emptyartık sadece bu nedenle kullanmamayı düşünüyorum .
julealgon

24

Bence burada çok fazla kafa karışıklığı ve kötü tepki var.

Her şeyden önce constalanlar staticüyedir ( örnek üyeler değil ).

Bölüm 10.4 C # dil spesifikasyonunun sabitlerini kontrol edin.

Sabitler statik üyeler olarak kabul edilmelerine rağmen, sabit bildirim statik bir değiştiriciye ne ihtiyaç duymaz ne de izin verir.

Eğer public constüye statik, biri sabit, yeni bir Object yaratacak düşünün olamazdı.

Bu göz önüne alındığında, aşağıdaki kod satırları yapmak tam olarak yeni bir Nesne yaratma konusunda aynı şeyi.

public static readonly string Empty = "";
public const string Empty = "";

İşte Microsoft'tan 2 arasındaki farkı açıklayan bir not:

Salt okunur anahtar kelime const anahtar kelimesinden farklıdır. Bir const alanı yalnızca alanın bildirilmesiyle başlatılabilir. Salt okunur bir alan, bildirimde veya bir kurucuda başlatılabilir. Bu nedenle, salt okunur alanlar kullanılan yapıcıya bağlı olarak farklı değerlere sahip olabilir. Ayrıca, bir const alanı derleme zamanı sabiti olsa da, salt okunur alan çalışma zamanı sabitleri için kullanılabilir ...

Bu yüzden buradaki tek makul cevabın Jeff Yates's olduğunu düşünüyorum.


Const ve statik salt okunur C # spec ile ilgili tür kelimeler ve açıklama için +1.
Jeff Yates

17
Bunu tekrar okuduğumda, buna katılmıyorum const stringve static readonly stringaynı şeyi yapıyorum. Sabit değerler bağlı kodda değiştirilirken, statik salt okunur değerlere başvurulur. Eğer bir varsa constkütüphane B tarafından kullanıldığını kütüphane A, kütüphane B o tüm başvuruları yerini alacak constolan edebi değeri olan değişken; bu değişken static readonlybunun yerine referans gösterilecek ve değeri çalışma zamanında belirlenecektir.
Jeff Yates

3
Jeff'in noktası kütüphanelere atıfta bulunurken önemlidir. A'yı yeniden derlerseniz ve B'yi yeniden derlemeden yeniden dağıtırsanız , B eski değerleri kullanmaya devam eder.
Mark Sowul

5
String.Empty read only instead of a constant?

Herhangi bir dize sabit yaparsanız , derleyici, aradığınız her yerde gerçek dize ile değiştirilir ve kodunuzu baştan sona aynı dize ile doldurursunuz ve kod çalıştığında da bu dizeyi farklı bellekten tekrar tekrar okuması gerekir. veri.

Dizenizi olduğu gibi yalnızca tek bir yerde okursanız String.Empty, program aynı dizeyi yalnızca tek bir yerde tutar ve okur ya da ona başvurur - verileri minimum bellekte tutar.

Dize const olarak String.Empty kullanarak herhangi bir dll derlemek ve herhangi bir nedenle String.Empty değiştirmek, o zaman derlenmiş dll artık aynı çalışmaz, çünkü costiç kodu aslında dizenin bir kopyasını tutmak için her çağrıda.

Örneğin bu koda bakın:

public class OneName
{
    const string cConst = "constant string";
    static string cStatic = "static string";
    readonly string cReadOnly = "read only string";

    protected void Fun()
    {
        string cAddThemAll ;

        cAddThemAll = cConst;
        cAddThemAll = cStatic ;
        cAddThemAll = cReadOnly;    
    }
}

derleyici tarafından aşağıdaki gibi gelecektir:

public class OneName
{
    // note that the const exist also here !
    private const string cConst = "constant string";
    private readonly string cReadOnly;
    private static string cStatic;

    static OneName()
    {
        cStatic = "static string";
    }

    public OneName()
    {
        this.cReadOnly = "read only string";
    }

    protected void Fun()
    {
        string cAddThemAll ;

        // look here, will replace the const string everywhere is finds it.
        cAddThemAll = "constant string";
        cAddThemAll = cStatic;
        // but the read only will only get it from "one place".
        cAddThemAll = this.cReadOnly;

    }
}

ve montaj çağrısı

        cAddThemAll = cConst;
0000003e  mov         eax,dword ptr ds:[09379C0Ch] 
00000044  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cStatic ;
00000047  mov         eax,dword ptr ds:[094E8C44h] 
0000004c  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cReadOnly;
0000004f  mov         eax,dword ptr [ebp-3Ch] 
00000052  mov         eax,dword ptr [eax+0000017Ch] 
00000058  mov         dword ptr [ebp-44h],eax 

Düzenle: Yazım hatası düzeltildi


Yani, bu, const dizesinin her zaman bu const'u içeren sınıfla başlatılması gerektiği anlamına gelir? O zaman statik salt okunur kullanmak çok daha iyi görünüyor.
Savaşçı

@theberserker daha iyidir, ancak kullanmak için tüm seçeneklere sahipsiniz.
Aristos

> sonra derlenmiş dll artık aynı çalışmayacak, çünkü maliyet aslında her çağrıda dizenin bir kopyasını tutmak için iç kodu yapmak. @Aristos Bu doğru değil. Kod derlendikten sonra, dizenin "kopyası" çalıştırılabilir dosyanın METİN bloğunda referans gösterilecektir ve tüm kod sadece aynı bellek bloğuna referans verecektir. İkinci adımınızda belirttiğiniz şey, sadece bir ara adımdır.
Peter Dolkens

@ user1533523 not için teşekkür ederim - Bunu kontrol etmek için biraz zaman bulduğumda bir test yapacağım
Aristos

Bu montaj kodunu nasıl aldın? C # derleme derlemez!
jv110

0

Bu cevap tarihsel amaçlar için var.

Aslında:

Çünkü Stringbir sınıftır ve bu nedenle sabit olamaz.

Genişletilmiş Tartışma:

Bu yanıtı incelemek için birçok yararlı iletişim kutusu ortaya çıkarıldı ve bu içerik silinmek yerine doğrudan yeniden üretildi:

.NET'te, (Java'dan farklı olarak) dize ve Dize tam olarak aynıdır. Ve evet, .NET'te dize değişmez sabitleri olabilir - DrJokepu 3 '09 saat 16:57

Bir Sınıfın sabitleri olamayacağını mı söylüyorsunuz? - StingyJack 3 '09, 16:58

Evet, nesnelerin salt okunur kullanması gerekir. Yalnızca yapılar sabitler yapabilir. Bence derleyici stringyerine kullandığınızda Stringconst sizin için bir salt okunur haline değiştirir. Tüm bunlar C programcılarını mutlu etmekle ilgilidir. - Garry Shutler 3 '09, 16:59

tvanfosson biraz daha ayrıntılı anlattı. "X sabit olamaz, çünkü Y içeren bir sınıftır" biraz fazla bağlamsızydı;) - Leonidas 3 Şubat 09: 17'de

string.Empty, string sınıfının kendisini değil, String sınıfının bir örneğini, yani boş dize döndüren statik özelliktir. - tvanfosson 3 '09, 17:01

Empty, String sınıfının salt okunur bir örneğidir (bir özellik değildir). - senfo 3 Şub0 17:02

Baş ağrısı. Hala haklı olduğumu düşünüyorum, ama şimdi daha az eminim. Bu gece araştırma gerekli! - Garry Shutler 3 '09, 17:07

Boş dize, dize sınıfının bir örneğidir. Boş, String sınıfında statik bir alandır (bir özellik değil, düzeltilmiş olarak duruyorum). Temel olarak bir işaretçi ve işaret ettiği şey arasındaki fark. Eğer salt okunur değilse, Boş alanının hangi örneğe başvurduğunu değiştirebiliriz. - tvanfosson 3 '09, 17:07

Garry, araştırma yapmana gerek yok. Bunu düşün. String bir sınıftır. Empty, bir String örneğidir. - senfo 3 Şubat 09:12

Oldukça alamadım bir şey var: nasıl yeryüzünde String sınıfının statik yapıcısı String sınıfının bir örneğini oluşturabilir? Bu bir çeşit "tavuk ya da yumurta" senaryosu değil mi? - DrJokepu 3 '09, 17:12 5

Bu yanıt System.String dışında hemen hemen tüm sınıflar için doğru olacaktır. .NET, dizeler için çok sayıda özel performans kasası yapar ve bunlardan biri, dize sabitlerine sahip olabileceğinizdir, sadece deneyin. Bu durumda, Jeff Yates doğru cevaba sahiptir. - Joel Mueller 3 '09, 19:25

§7.18'de açıklandığı gibi, sabit bir ifade derleme zamanında tam olarak değerlendirilebilen bir ifadedir. Dize dışında bir başvuru türü null olmayan bir değer oluşturmanın tek yolu yeni işleci uygulamak olduğundan ve sabit bir ifadede yeni işlece izin verilmediğinden, başvuru türlerinin sabitleri için olası tek değer string dışında null. Önceki iki yorum doğrudan C # dil spesifikasyonundan alındı ​​ve Joel Mueller'in bahsettiklerini tekrarladı. - senfo 4 '09, 15:05 5


Lütfen doğru cevabı oylayın. Tanıma Git yaparsanız, bunun String sınıfında olduğunu ve String'in bir örneği olduğunu görürsünüz. Küçük harf olarak gösterilmesi derleyici büyüsüdür.
Garry Shutler

Seni indiremeyen ben değildim ama .NET'te (Java'da aksine) string ve String tamamen aynı. Ve evet, .NET'te dize değişmez sabitleri olabilir
Tamas Czinege

10
Bu yanıt System.String dışında hemen hemen tüm sınıflar için doğru olacaktır. .NET, dizeler için çok sayıda özel performans kasası yapar ve bunlardan biri, dize sabitlerine sahip olabileceğinizdir, sadece deneyin. Bu durumda, Jeff Yates doğru cevaba sahiptir.
Joel Mueller

7
Bu yanıtı çok daha iyi bir cevap geldiğinden neredeyse sildim, ancak bu yorumlardaki tartışma tutmaya değer.
Garry Shutler

1
@Garry, son yorumunu okuduğum için şanslısın, aksi halde aşağıya da oylardım. Dize, .NET'te özel bir özelliğe sahiptir, bu nedenle bir ref sınıfı olabilir.
Shimmy Weitzhandler
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.