在學習 design&pattern 的 singleton pattern 的時候,因為靜態初始化是在 .net 中實現 singleton 的首選方法.
1public
sealed
class
singleton28
9singleton()
1012
13public
static
singleton instance
1419}20
} 不過我對於靜態建構函式還是有點迷惑!它和例項化物件時的建構函式有什麼區別,它們的關係又是什麼呢?
檢視了相關資料後現在對它有了一定的認識了!
靜態成員的初始化語句會早於靜態建構函式執行,其次靜態建構函式是由clr呼叫執行的,所以靜態建構函式只能是乙個,同時不能還有引數。那麼靜態建構函式相對於成員初始化的一些弊端都不復存在。
對於靜態成員何時被初始化,靜態建構函式又何時被呼叫,它們之間的先後順序又是怎麼樣的呢?下面我們給出乙個例子來說明一下!
1using
system;23
namespace
teststatic414
}1516classa17
24}25classb26
33}34}
說實話我在以前對於 static 的認識的基礎上我真的不知道上面的會返回什麼值!(做人得誠實,不懂不能裝懂!呵呵...).其結果是「2,1」,也就是
a.x的值為2,
b.y的值為1.
分析此類問題,只要記住三點就行了:
1. **的執行順序,**在前的先執行;
2. 靜態成員初始化語句要先於靜態建構函式執行;
3. 靜態成員初始化語句與靜態建構函式只執行一次。
如果了解這三點,接下來就分析為什麼會出現上面的結果。
當呼叫到第一條語句的時候:
console.writeline(a.x.tostring());
首先是訪問a這個型別,那麼要對a這個型別的靜態成員進行初始化,其次如果有靜態建構函式,需要呼叫它。對於a的靜態成員只有「x」,按照上一單元的過程,先給其分配空間,並輔以0來初始化,其次呼叫其對應的成員初始化語句來初始化這個靜態成員。那麼它的成員初始化語句是「x = b.y」,那麼需要訪問「b.y」來初始化x這個靜態成員。
對於「b.y」的訪問,就是訪問b型別,也是和訪問a一樣,首先對這個型別的靜態成員進行初始化,其次如果有靜態建構函式,需要呼叫它。而b的靜態成員只有「y」,先給其分配空間,並輔以0來初始化,其次呼叫其對應的成員初始化語句來初始化這個靜態成員。
那麼對於「y = a.x」成員初始化語句,由於此時不是第一次訪問型別a,所以不再進行靜態成員初始化和靜態建構函式的呼叫,對於「a.x」的訪問是直接訪問。此時「a.x」的值為0,那麼y的值也為0;接著執行b的靜態建構函式,這樣處理後y的值為1。那麼對於a中的成員初始化語句「x = b.y」,到此就執行完了,此時a型別中的x與b型別中的y都是一樣的,值為1。不過b中的靜態成員初始化語句和靜態建構函式都執行過了,而a中的靜態建構函式還未執行。因此經過a的靜態建構函式處理,a的x值為2,這也就是最後顯示的結果。
為了再加深一下對 static 的印象,再個小的測試片斷!這下就對 static 印象更深了~~`
1using
system;
2using
system.collections.generic;
3using
system.text;
4using
system.threading;56
namespace
teststatic720
}2122classa23
38private
a()39
4243
public
string
getstr()
4447
48public
static
a instance
4955}56
5758}59
classb60
7172
73///
74///
只有物件被例項化的時候才會呼叫非靜態建構函式
75///
76private
b()7780}
81}
輸出為:
hello b . i am from static b constructor
hello a. i am from static a constructor
hello a. i am from private a constructor
i am a, i am a member of class a
先看個例子:
1using
system;23
class a410
}1112class b
1316
17static
void
main()
18,y=
",a.x,b.y); 20}
2122}
執行結果是x=2,y=1
這個例子主要考查2個方面,一是static的用法,二是static的初始化順序。了解了static的初始化順序和規則,這個問題答答案就很容易理解了。這裡涉及到以下三類static物件:static成員,static方法,static建構函式。規則如下:
乙個類的static建構函式在給定的應用程式域中僅執行一次。static建構函式由在應用程式域的下列事件的首次發生時觸發:
1)該類的例項被建立。
2)任何乙個static成員被引用
3)如果類包含執行入口main方法,此類的static建構函式在main方法被呼叫之前執行。
4)如果類包含任何staic成員,則這些static成員在static建構函式之前進行初始化。
5)如果類包含任何static方法,則這些static方法在static建構函式之後進行初始化。
6)對於存在多個static成員,他們的初始化將按照文字順序進行,不會因為呼叫順序而改變。
現在看看上面的應用程式,class b中有個main執行入口,所以b首先得到初始化,順序是static成員y->static建構函式。在初始化y時,引用了a.x,編譯器又開始初始化class a(注意這時class b的初始化並沒有完成),順序也是static成員x->static建構函式。class a中x在定義的時候沒有被賦予初始值(在定義static變數時,盡量賦予初始值),編譯器會預設賦予值0(int型)。然後再執行static的建構函式,由於class b的初始化這時還沒有完成,所以b.y的值在這時被編譯器賦予預設值0,所以在a的static的建構函式執行完後,x的值變為1,然後返回b繼續完成初始化,得到y的值為2。最後執行main,輸出a.x和b.y的值。相反地,如果將b中的main方法移出放在乙個類c中,那執行結果又是什麼呢?依據以上的規則,可以很方便的得出答案。
以下這題可以用來說明規則六,有興趣的朋友可以思考一下答案
classclass1
public
static
class1 getinstance()
[stathread]
static
void
main(
string
args)}
C 學習筆記 對static的重新認識
static 這個修飾詞的意思,是為 靜態 在工作所用到的c工程中,時常看到其使用,但一直沒有太深的認識,最近在看了c 語言描述後,其中對與class類的成員定義中,有個更詳細的static修飾用法,使得我對static的認識比之之前更多了些。在我的c檔案中,我在一開始認為 對於全域性變數才用sta...
對「認識」的認識
很早就想談談關於 認識 的認識。這是乙個巨集大深刻的哲學問題。只是覺得沒有完全思考清楚,還以為觀點有些偏頗,擔心自己沒能力系統論述,就遲遲沒有動筆。但想到談論的問題本身就是乙個偏頗的問題,而且,我始終覺得,問題儘管偏頗,但卻不無道理。所以,提筆寫下這篇文字。正像思想的本質是不安一樣,認識的本質是片面...
對多型中的父類 子類的認識
對多型中的父類 子類的認識 多型的時候,要注意 子類特有功能,父類引用不能訪問。若需要訪問,可執行以下操作 a 建立子類物件即可。b 把以前的狗轉成真的狗。多型中的轉型 a 向上轉型 從子到父。b 向下轉型 從父到子。class animal class dog extendsanimal publ...