2014-07-24 51 views
13

Anlamak istediğim bir C# davranışıyla karşılaştım. Böyle bir sınıf düşünün:C# statik alan, örnek yapıcı

Şimdi
public class SomeSingleton 
{ 
    public static SomeSingleton Default = new SomeSingleton(); 

    private static int field = 0; 

    private SomeSingleton() 
    { 
     field = 1; 
    } 

    public int GetField() 
    { 
     return field; 
    } 
} 

, en GetField() yöntemini çağırın bakalım: örnek yapıcı atlandı sanki ben 0 alıyorum

var field = SomeSingleton.Default.GetField(); 

. Niye ya?

cevap

26

Default'dan önce field bildiriminin sırasını değiştirin.

Yani hatları:

public static SomeSingleton Default = new SomeSingleton(); 
private static int field = 0; 

olmalıdır:

private static int field = 0; 
public static SomeSingleton Default = new SomeSingleton(); 

nedeni saha başlatma düzenine kaynaklanmaktadır. İlk Default, 1 değerini atayan kodunuzda başlatılır. Daha sonra bu alana başlangıçta 0 atanır. Bu nedenle, 0'un en son değerini ve 1'u göremezsiniz.

Bkz: Bir sınıfın 10.4.5.1 Static field initialization

statik alan değişken ilklendiriciler onlar sınıf bildiriminde görünür yılında metinsel sırayla içinde yürütülür atamaları dizisine karşılık gelmektedir.

+1

Daha da iyisi, "alan" için başlatıcıyı tamamen kaldırın. Nesne ilk oluşturulduğunda tüm alanlar sıfırlanır (veya 'null') (statik alanlar için, tür ilk yüklendiğinde). –

3

Statik değişkenlerin sırasını değiştirin. Kodunuzda

private static int field = 0; 
public static SomeSingleton Default = new SomeSingleton(); 

, yapıcı field koyan ilk olarak çalışır ve sonra field değerini geçersiz kılar.

7

Bunun nedeni, static değişkenlerinin sıralanmasıdır. Eğer iki ifade geçerseniz, çıkış 1 olur: MSDN: Static field initialization belgelenen olarak

private static int field = 0; 

public static SomeSingleton Default = new SomeSingleton(); 

Bu beklenen bir davranıştır.

Bkz. this .NET Fiddle.

+4

+1 .NET Fiddle bağlantısı için mükemmel bir araç. –