Statik bir kurucu nasıl çalışır?


82
namespace MyNameSpace
{
    static class MyClass
    {
        static MyClass()
        {
            //Authentication process.. User needs to enter password
        }

        public static void MyMethod()
        {
            //Depends on successful completion of constructor
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.MyMethod();
        }
    }
}

İşte varsaydığım sıra

  1. Statik kurucunun başlangıcı
  2. Statik yapıcının sonu
  3. Ana başlangıç
  4. MyMethod'un başlangıcı
  5. Ana sayfanın sonu

Şimdi herhangi bir senaryoda 4'ten önce başlayacaksa 2'den önce vidalıyım. Mümkün mü?


8
Bu bir java mı yoksa c # sorusu mu? Her iki etiketi de koydunuz ve spesifikasyonun iki dilde aynı olduğunu düşünmüyorum.
ARRG

Açıklamamda bu her ikisi için de aynı işe yarıyor .. Ama ben C # adamım .. Bunun için
üzgünüm

4
Java'nın aynı şekilde statik bir kurucusu yoktur, sadece statik başlatma için statik bloklar vardır. statik {// bir şeyler yap ...}
deraj

2
Kişisel olarak, statik bir kurucu içindeki herhangi bir etkileşim biçiminden rahatsızlık duyuyorum. Amacınızı anlıyorum (bu statik sınıftaki her yöntemi, çalışmasına izin vermeden önce kullanıcının yetkilendirilmesini bekletir), ancak bunu gerçekleştirmenin bu yöntemini gerçekten beğenmedim.
Brian

@Brian: - Evet ... Haklısın ... Sadece analiz yapıyordum .. Sonunda
yapıcıyı

Yanıtlar:


220

Burada sadece bir soru sordunuz ama sormanız gereken bir düzine kadar soru var, bu yüzden hepsini cevaplayacağım.

İşte varsaydığım sıra

  1. Sınıf yapıcısının başlangıcı (aynı zamanda olarak da bilinir cctor)
  2. Cctor sonu
  3. Ana Başlangıcı
  4. MyMethod'un başlangıcı

Bu doğru mu?

Hayır. Doğru sıra:

  1. Varsa Program için cctor başlangıcı. Yok.
  2. Varsa Program için cctor sonu. Yok.
  3. Ana Başlangıcı
  4. MyClass için cctor başlangıcı
  5. MyClass için cctor sonu
  6. MyClass.MyMethod başlangıcı

Ya statik bir alan başlatıcı varsa?

CLR'nin, bazı durumlarda statik alan başlatıcılarının çalıştığı sırayı değiştirmesine izin verilir. Ayrıntılar için konuyla ilgili Jon'un sayfasına bakın:

Statik oluşturucular ve tür başlatıcılar arasındaki farklar

Bu MyMethodsınıfın cctoru tamamlanmadan önce çağrılması gibi statik bir yöntemin olması mümkün mü ?

Evet. Eğer cctor kendisi MyMethod'u çağırırsa, belli ki, cctor tamamlanmadan önce MyMethod çağrılacaktır.

Bilgi sahibi, MyMethod'u çağırmaz. MyMethodMyClass'ın cctoru tamamlanmadan önce çağrılması gibi statik bir yöntemin olması mümkün mü ?

Evet. Cctor, Cctor MyMethod'u çağıran başka bir tür kullanıyorsa, MyClass cctor tamamlanmadan önce MyMethod çağrılacaktır.

Hiçbir uzman, doğrudan veya dolaylı olarak MyMethod'u çağırmaz! Şimdi, MyMethodMyClass'ın cctoru tamamlanmadan önce çağrılması gibi statik bir yöntem mümkün mü?

Hayır.

Birden fazla iş parçacığı olsa bile bu hala doğru mu?

Evet. Statik yöntem herhangi bir iş parçacığında çağrılmadan önce cctor bir iş parçacığında bitirecektir.

Görevli birden fazla aranabilir mi? İki iş parçacığının her ikisinin de cctor'un çalışmasına neden olduğunu varsayalım.

Cctor, kaç iş parçacığı dahil olursa olsun, en fazla bir kez çağrılacağı garantilidir. İki iş parçacığı "aynı anda" MyMethod'u çağırırsa, yarışırlar. Bunlardan biri yarışı kaybeder ve MyClass cctor kazanan iş parçacığını tamamlayana kadar bloklar.

Kaybetme iplik blokları cctor kadar yapılır? Gerçekten mi?

Gerçekten mi.

Peki ya kazanan iş parçacığındaki cctor , kaybeden iş parçacığı tarafından daha önce alınan bir kilidi engelleyen kodu çağırırsa ?

O zaman klasik bir kilit sırası ters çevirme koşuluna sahipsiniz. Programınız kilitleniyor. Sonsuza dek.

Bu tehlikeli görünüyor. Çıkmazdan nasıl kaçınabilirim?

Bunu yaptığında canın yanarsa, o zaman yapmayı bırak . Asla bir cctor'u engelleyebilecek bir şey yapma.

Karmaşık güvenlik gereksinimlerini uygulamak için cctor başlatma semantiğine güvenmek iyi bir fikir mi? Ve kullanıcı etkileşimlerini gerçekleştiren bir uzmana sahip olmak iyi bir fikir mi?

İyi fikirler de değil. Benim tavsiyem, yöntemlerinizin güvenliği etkileyen ön koşullarının karşılanmasını sağlamak için farklı bir yol bulmanız gerektiğidir.


5
Eric, bu yanıtta neden "statik yapıcı" yı "sınıf oluşturucu" veya "cctor" ile değiştirdiğinizi merak ediyorum. Bir cctor'a atıfta bulunurken "statik yapıcı" kullanmak doğru mu?
phoog

6
@phoog: Terminoloji kullanımımda tutarlı olmak istedim, bu yüzden en kısa olanı seçtim. "Statik yapıcı" ve "sınıf oluşturucu" her ikisi de iyidir. Bir uygulama ayrıntısı olarak, bir türün statik kurucusu ".cctor" adı verilen özel bir yöntem olarak yayınlanır, bu nedenle böyle bir kurucuya "cctor" olarak atıfta bulunmak yaygındır. Daha resmi bir bağlamda yazsaydım, daha uzun terimlerden birini kullanırdım.
Eric Lippert

@EricLippert Bu, statik oluşturuculu statik olmayan sınıflar için de geçerli mi?
Efsaneler

2
@Legends: Bu, statik oluşturucuya sahip statik olmayan sınıflar için de geçerli mi? Evet.
Eric Lippert

24

Göre MSDN , statik yapıcı:

İlk örnek oluşturulmadan veya herhangi bir statik üyeye başvurulmadan önce sınıfı başlatmak için otomatik olarak statik bir oluşturucu çağrılır.

Dolayısıyla, statik kurucu, statik yöntem çağrılmadan önce çağrılacaktır (tabii ki statik yapı veya statik alan başlatma sırasında da çağrılmadığı MyClass.MyMethod()varsayılır ).

Şimdi, eğer static constructorbunun içinde eşzamansız bir şey yapıyorsanız , o zaman bunu senkronize etmek sizin işinizdir.


7
Statik bir kurucuda ikinci bir iş parçacığı içeren eşzamansız bir şey yapıyorsanız , acı dolu bir dünyanın içindesiniz . Hiçbir şey kilitlenmeleri daha hızlı yapmaz. Örnek için stackoverflow.com/a/8883117/88656 adresine bakın .
Eric Lippert

@Eric: anlaşılan ... Ben bunu yapmak istemem, ama emin tam olarak o zaman MyMethod bitirilmesi isteyen ne onu örnek ... çağrıldı oluştururlar değildi
James Michael Hare

11

3 numara aslında 1 numaradır: statik başlatma, ait olduğu sınıfın ilk kullanımına kadar başlamaz.

MyMethodStatik kurucudan veya statik bir başlatma bloğundan çağrılması mümkündür . MyMethodStatik kurucunuzdan doğrudan veya dolaylı olarak çağırmazsanız, iyi olmalısınız.


Bir not olarak, benim anlayışıma staticgöre, optimizasyonlar için uygunluğa bağlı olarak ilk kullanımdan önce başlatma çağrılabilir.
James Michael Hare


1
Statik bir kurucu için doğru, ancak statik başlatma için benim amacım buydu. Üzgünüm, belki de 'statik başlatma başlamıyor ...' deyiminden nit seçiyordum, bu statik yapı için doğrudur, ancak sınıfın statik kurucusu yoksa, o zaman statik başlatma daha önce gerçekleşebilir.
James Michael Hare

Üzgünüm, muhtemelen laf kalabalığını aşırı analiz ediyorum. Kesinlikle doğru olduğu sorusu bağlamında, bu cümlenin açık statik oluşturucular olmadan sınıflar bağlamında statik başlatma için bağımsız bir ifade olarak endişeleniyordum.
James Michael Hare

@James: Fazla analiz etmiyorsunuz - terminoloji buradaki en önemli fark. Statik oluşturucular bir C # kavramıdır, oysa tür başlatma bir .NET şeyidir. Statik bir kurucu (C #) içindeki kod, initialiser (.NET) türünün bir parçası haline gelir, ancak tür başlatıcının ne zaman ve nasıl tetikleyeceği (yani, beforefieldinitanlambilim), C # sınıfının statik bir kurucuya sahip olup olmadığına göre belirlenir.
LukeH

9

Gönderen belgelerinde (vurgu benim):

İlk örnek oluşturulmadan veya herhangi bir statik üyeye başvurulmadan önce sınıfı başlatmak için otomatik olarak statik bir oluşturucu çağrılır .


2

4'ün her zaman 2'den sonra geleceğini garanti edebilirsiniz (statik yönteminizden sınıfınızın bir örneğini oluşturmazsanız), ancak aynı durum 1 ve 3 için geçerli değildir.


2

Statik kurucu, mymethod çalıştırılmadan önce çağrılacaktır. Ancak eğer mahvolursanız, 2'den önce 4 aranırsa, tasarımınızı yeniden düşünmenizi öneririm. Zaten statik bir kurucuda karmaşık şeyler yapmamalı.


2

CLR, statik oluşturucunun herhangi bir statik üyeye erişilmeden önce çalıştığını garanti eder. Ancak tasarımınız biraz kokuyor. Bunun gibi bir şey yapmak daha kolay olacaktır:

static void Main(string[] args) 
{ 
     bool userIsAuthenticated = MyClass.AuthenticateUser();
     if (userIsAuthenticated)
         MyClass.MyMethod(); 
 } 

Tasarımınızla, kimlik doğrulama başarısız olursa, MyMethod'un çalışmasını önlemenin tek yolu bir istisna atmaktır.


2

Statik bir sınıfın yapıcısının, yöntemlerinden herhangi biri çalıştırılmadan önce çağrılması sağlanır. Misal:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Press enter");
        Console.ReadLine();
        Boop.SayHi();
        Boop.SayHi();
        Console.ReadLine();
    }

}

static class Boop
{
    static Boop()
    {
        Console.WriteLine("Hi incoming ...");
    }

    public static void SayHi()
    {
        Console.WriteLine("Hi there!");
    }
}

Çıktı:

Enter'a bas

// enter tuşuna bastıktan sonra

Merhaba, geliyorum ...

Merhaba!

Merhaba!


Sistem kullanarak; ad alanı MyNameSpace {class Program {static void Main (string [] args) {Console.WriteLine ("Entered in main"); Boop.SayHi (); Boop.SayHi (); }} statik sınıf Boop {statik Boop () {Console.Read (); Console.WriteLine ("Oluşturucu anahtarı girildi"); } public static void SayHi () {Console.WriteLine ("Yöntem çağrılır"); }}} evet bu program daha iyi bir anlayış sağlıyor
om471987

Muhtemelen. Yine de bir dahaki sefere bir cevap olarak gönderin. O zaman daha yararlı ve görünür.
haiyyu

1

İşte işlerin düştüğü gerçek sıra:

  1. Başlamak Main
  2. Statik MyClassyapıcının başlangıcı
  3. Statik MyClassoluşturucunun sonu
  4. Başlamak MyMethod
  5. Sonu Main

0

Veya hata ayıklayıcıda adım adım ilerleyebilirsiniz.

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.