Singleton - Jon Skeet açıklama


214
public sealed class Singleton
{
    Singleton() {}

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested() {}
        internal static readonly Singleton instance = new Singleton();
    }
}

Ben uygulamak isteyen Jon Skeet en Singleton deseni C # benim şimdiki uygulamada.

Kodda iki şüphem var

  1. Yuvalanmış sınıfın içindeki dış sınıfa erişmek nasıl mümkün olur? Demek istediğim

    internal static readonly Singleton instance = new Singleton();

    Kapanma denen bir şey var mı?

  2. Bu yorumu anlayamıyorum

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit

    bu yorum bize ne öneriyor?


12
haha Bunun biraz endişelendiğini söylemiştim sandım ... farklı bir John Nolan
John Antony Daniel Nolan olduğu ortaya çıktı

14
İki şey evrensel olarak kabul edilir: güneş doğudan doğar ve Jon Skeet her zaman haklıdır. Ama henüz eski hakkında emin değilim: P
akhil_mittal

2
@ thepirat000 - Eğer sadece SO / Meta'ya katılmış olsaydım, katılmıyorum, ama gerçek programlama dünyasında gerçekten yasal olabilecek yeterli etkiye sahip - eminim birisi onu bir noktada yarattı .
Kod Jokey

8
Bu sorunun taksonomisi meta üzerinde tartışılmaktadır .
BoltClock

Yanıtlar:


359
  1. Hayır, bu kapaklarla bir ilgisi yok. Yuvalanmış bir sınıf, burada özel kurucu da dahil olmak üzere dış sınıfının özel üyelerine erişebilir.

  2. Önceden alandaki makalemi okuyun . Op-statik statik yapıcıyı isteyebilir veya istemeyebilirsiniz - ihtiyacınız olan tembellik garantisine bağlıdır. .NET 4'ün gerçek tür başlatma semantiğini bir şekilde değiştirdiğinin farkında olmalısınız (yine de spesifikasyon dahilinde, ancak öncekinden daha tembel).

Eğer Do gerçekten olsa bu modeli gerek? Şunlardan kaçamayacağınızdan emin misiniz:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();
    public static Singleton Instance { get { return instance; } }

    static Singleton() {}
    private Singleton() {}
}

12
@Anindya: Hayır, sorun değil. Gerçi şikayet etmek için JetBrains'e mail atmak isteyebilirsiniz :)
Jon Skeet

2
@JonSkeet, bu konuda JetBrains için endişe duydum (# RSRP-274373). Bakalım neler bulabilecekler. :)
Anindya Chatterjee

3
@ Moons: Yapmazsın. AppDomain süresince bir singleton yaşıyor.
Jon Skeet

2
@JonSkeet Lazy<T>Sihirli BeforeFieldInityan etki için statik bir yapıcı bildirmek zorunda kalmamanız için herhangi bir sebep yok mu?
Ed T

3
FieldBeforeInitolduğu MahaBharatagelenMicrosoft
Amit Kumar Ghosh

49

Soru (1) ile ilgili olarak: Jon'un cevabı doğrudur, çünkü 'Nested' sınıfını herkese açık veya dahili hale getirerek örtük olarak işaretler :-). 'Özel' ekleyerek de bunu açıkça yapabilirsiniz:

    private class Nested

Soru (2) ile ilgili olarak: temel olarak beforeinitfield ve type başlatma ile ilgili mesajın size söylediği şey, statik bir kurucunuz yoksa, çalışma zamanının herhangi bir zamanda (ancak kullanmadan önce) başlatabileceğidir. Statik bir kurucunuz varsa, statik kurucudaki kodunuz alanları başlatabilir, bu da çalışma zamanının yalnızca türü istediğinde alanı başlatmasına izin verildiği anlamına gelir.

Bu nedenle, çalışma zamanının alanları kullanmadan önce 'proaktif' olarak başlatmasını istemiyorsanız, statik bir yapıcı ekleyin.

Her iki durumda da, singletonları uyguluyorsanız, çalışma zamanının değişkeninizi başlatması gerektiğini düşündüğünde değil, mümkün olduğunca tembel olarak başlatılmasını istersiniz - ya da muhtemelen umursamıyorsunuzdur. Sorunuzdan sanırım onları mümkün olduğunca geç istiyorsunuz.

Bu, Jon'un singleton hakkında gönderdiği mesajla bir araya geldi , IMO bu sorunun altında yatan konudur. Ah ve şüpheler :-)

'Yanlış' olarak işaretlediği singleton # 3'ün aslında doğru olduğunu belirtmek isterim (çünkü kilit otomatik olarak çıkışta bir bellek bariyeri anlamına gelir ). Örneği bir kereden fazla kullandığınızda (tek bir noktanın az ya da çok :-) noktasıdır) ayrıca 2. tektondan daha hızlı olmalıdır. Yani, gerçekten tembel bir singleton uygulamasına ihtiyacınız varsa, muhtemelen bunun için giderdim - basit nedenlerden dolayı (1) neler olup bittiğini okuyan herkes için çok açık ve (2) neler olacağını biliyorsunuz istisnalar hariç.

Merak ediyorsanız: asla singleton # 6'yı kullanmam çünkü istisnalarla kolayca kilitlenmelere ve beklenmedik davranışlara yol açabilir. Ayrıntılar için bkz: tembel kilitleme modu , özellikle ExecutionAndPublication.


62
Regarding question (1): The answer from Jon is correct ...Jon Skeet her zaman doğrudur ....
Noctis

72
Jon Skeet'in zaten cevapladığı bir Jon Skeet sorusu hakkında cevap vermeye çalışmak için ekstra puan.
valdetero

8
@valdetero Hahaha. This ... hahaha +1
akinuri
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.