2009-05-19 67 views
2

你有什麼想法,爲什麼下面的代碼:有趣的功能與靜態字段。 StackOverflow的例外

public class A 
{ 
    public static int i = B.i + 1; 
} 

public class B 
{ 
    public static int i = A.i + 1; 
} 

有:

 int aa = A.i; 
     int bb = B.i; 

說是AA = 2(!!!)和BB = 1

我的腦中有堆疊溢出! 據我瞭解,遞歸停止在靜態方法,但爲什麼? 如果你把int重新映射到getters(爲了調試和理解它爲什麼會像這樣工作),你會得到堆棧溢出異常。

+0

多態性功能? – bzlm 2009-05-19 16:01:30

+0

不知道爲什麼這個改變了。 – 2009-05-19 16:04:27

回答

6

毫無疑問的執行正在發生的事情,像這樣:

B.i靜態初始化第一次運行,並設置B.i = A.i + 1。由於A.i尚未初始化,因此A.i等於default(int),即0B.i獲得值1

A.i靜態初始化器運行第二個,並設置A.i = B.i + 1 = 2

由於靜態初始化器以未定義的順序運行,因此每次運行時都會發現其他字段爲2,或者在對代碼進行其他結構更改時發生切換。然而,總是應該結束爲2,而且應該總是1

P.S.這與多態性無關。

編輯:對於靜態初始化和建設者的時機一些進一步的瞭解,可能要檢查this relevant portion of the C# specification.

4

一個字段不像屬性獲得者。它只是存儲數據,而不是任何操作。事實上,初始化將被移動到另一個方法(靜態構造函數,.cctor),它將初始化類中的靜態變量。

開始時,兩者都等於0.在您首​​次訪問A.i之前,運行類A的方法.cctor。它首次嘗試訪問B.i,這將導致執行類B的靜態構造函數。 .cctorB將嘗試訪問A.i,但由於它不是第一次訪問某個字段,所以A的靜態構造函數將會而不是運行了。它只是獲取當前值A仍爲0.因此,當B..cctor完成執行並且控制返回到A..cctor時,B.i將等於1。它將看到值B.i並將其加1並將其存儲在A.i中。因此,A.i將等於2(1 + 1)和B.i將等於1

你唯一能把握的是,靜態構造函數將被調用之前類的任何靜態成員訪問。

1

這裏發生了什麼。

  • A被首次訪問。
  • A.i創建值爲0.
  • A的靜態初始值設定項運行。
  • B是第一次訪問。我們訪問了A.i,即
  • 。它目前擁有價值0.1
  • 碧設置爲1艾設定爲2

要注意的真正重要的是,靜態屬性被初始化爲默認值和然後靜初始化器運行。

就我個人而言,我儘量避免靜態初始化,靜態和其他。有太多的陷阱。