2009-04-02 20 views
18

Yapıcı çağrılmadan önce statik alan başlatması tamamlansın mı?Statik alan başlatması C# nasıl çalışır?

Aşağıdaki program, bana yanlış görünen çıktılar sağlar.

new A() 
_A == null 
static A() 
new A() 
_A == A 

kodu:

public class A 
{ 
    public static string _A = (new A()).I(); 

    public A() 
    { 
     Console.WriteLine("new A()"); 
     if (_A == null) 
      Console.WriteLine("_A == null"); 
     else 
      Console.WriteLine("_A == " + _A); 
    } 

    static A() 
    { 
     Console.WriteLine("static A()"); 
    } 

    public string I() 
    { 
     return "A"; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var a = new A(); 
    } 
} 

cevap

22

Bu doğrudur.

Statik başlatıcılarınız, daha sonra statik yapıcınız standart yapıcınızdan önce çalışır, ancak çalışırken, yeni A() kullanır, böylece statik olmayan yapıcı yolunuzu iletir. Bu, gördüğünüz iletilere neden olur.

İşte infaz tam yol:

programınızda ilk çağrı var a = new A();, bu A erişilen ilk kez

. Bu, bu noktada A._A

statik başlatma ateşlenmesine

, A._A Bu


Console.WriteLine("new A()"); 
if (_A == null) 
    Console.WriteLine("_A == null");   

vurur _A = (new A()).I();

bu noktada _A olmamıştır beri birlikte inşa döndürülen, oluşturulmuş tiple (henüz) ayarlayın.

Sonraki, statik yapıcı A { static A(); } çalıştırılıyor. Bu "statik A()" mesajını yazdırır.

Son olarak, orijinal beyanı ( var a = new A();) yürütüldüğünde, ancak bu noktada, statik inşa edilir, böylece nihai baskı olsun.

+0

Dang! Beni ona yen! –

+0

Tüm saygımla ... statik kurucu önce çalışmaz. Statik alan başlatıcısı ilk önce çalışır. – Prankster

+1

A._A'nın yapısı statik yapıcıda gerçekleşir. Derleyici, C# statik yapıcıda bildirilen kodun önündeki tüm alan başlatımlarını statik yapıcıda (.cctor) hazırlar. –

-1

Evet, statik alan başlatması yapıcı çağrılmadan önce tamamlanmalıdır. Fakat derleyiciyi olağandışı bir duruma soktunuz ve bu kurala uymayacaksınız.

Bu ilginç hiledir, ama her şey normale uygulamada olmayacak.

1

Aslında düşündüğün yapıyor inanıyoruz. Testin söylemek zor. _A

public static string _A = (new A()).I(); 

İlk A'nın yeni bir örneğini oluşturur için

Sizin initalization, yeni A() ve _A = null böylece sizin yazıları. Başlamadan beri null olduğu için, bu başlatmadır. initalized sonra, statik yapıcı yeni bir örneğini döndüren denir.

0

derleyici beklenen yapıyor gibi görünüyor.

1 - Bütün statik kod sınıfında (alanlar, sonra statik yapıcı) yürütülür: - Sınıf yapıcısı denir

public static string _A = (new A()).I(); 

// and 

static A() 
{ 
    Console.WriteLine("static A()"); 
} 

2:

public A() 
{ 
    Console.WriteLine("new A()"); 
    if (_A == null) 
     Console.WriteLine("_A == null"); 
    else 
     Console.WriteLine("_A == " + _A); 
} 

Sormak bu neden mümkündür. Benim düşünceme göre, bir örnek kesinlikle tüm sınıf değişkenlerinin yaratılış üzerine başlatılmasını gerektirmez. Sadece var olmalarını gerektiriyor. Bu özel durumun bu düşünceyi desteklediğini düşünüyorum çünkü tüm statik başlatmadan önce bir örnek oluşturuldu.

0

Bir ilave yan not - C# şartname (ı 4.0 bakıyorum, ama çok 3.0'da yoktur) diyor 10.5.5.1 Statik Alan başlatma içinde:

Bir statik yapıcı (§10.12) sınıfında mevcut, statik alan başlatıcılarının çalıştırılması, statik yapıcısını çalıştırmadan hemen önce oluşur. Aksi takdirde, statik alan başlatıcıları, bu sınıfın bir statik alanının ilk kullanımından önce, uygulamaya bağlı bir zamanda uygulandığında yürütülür.

Statik bir kurucunuz var, bu nedenle "Aksi takdirde" yan tümcesi geçerli değil. Ancak, statik bir kurucunuz yoksa statik alan başlatıcılarının 'uygulamaya bağlı bir zamanda' yürütülebileceğini bilmenizi isterim. Statik alan başlatıcınız, statik alanın kendisine erişmeden güvenebileceğiniz bir tür veri başlatma veya nesne oluşturma işlemi gerçekleştiriyorsa bu önemli olabilir.

Bu ezoterik, sanırım, ama bugün 'uygulama-bağımlı zaman' C-3.0 ve 4.0 arasında değişmiş gibi göründüğünü gördüm - en azından baktığım durum için. Elbette kolay bir çözüm basit - sadece statik bir kurucu ekleyin ...

İlgili konular