對Static 類的認識

2021-09-07 21:34:00 字數 3665 閱讀 7162

在學習 design&pattern 的 singleton pattern 的時候,因為靜態初始化是在 .net 中實現 singleton 的首選方法.

1

public

sealed

class

singleton28

9singleton()

1012

13public

static

singleton instance

1419}20

} 不過我對於靜態建構函式還是有點迷惑!它和例項化物件時的建構函式有什麼區別,它們的關係又是什麼呢?

檢視了相關資料後現在對它有了一定的認識了!

靜態成員的初始化語句會早於靜態建構函式執行,其次靜態建構函式是由clr呼叫執行的,所以靜態建構函式只能是乙個,同時不能還有引數。那麼靜態建構函式相對於成員初始化的一些弊端都不復存在。

對於靜態成員何時被初始化,靜態建構函式又何時被呼叫,它們之間的先後順序又是怎麼樣的呢?下面我們給出乙個例子來說明一下!

1

using

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 印象更深了~~`

1

using

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

先看個例子:

1

using

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中,那執行結果又是什麼呢?依據以上的規則,可以很方便的得出答案。

以下這題可以用來說明規則六,有興趣的朋友可以思考一下答案

class

class1

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...