關於靜態建構函式和BeforeFieldInit

2021-07-24 13:05:57 字數 2867 閱讀 5438

**     生魚片大神的博文

1.看下面的例子:

public

static

class

myclass

}class

program

}結果如下:

getnow execute!

getnow execute!

main execute!

int: 2009/9/8 15:34:31

string: 2009/9/8 15:34:31

看上面的結果在main函式執行之前getnow就執行了,就取到了datetime.now,所以輸出的時間是一樣的。

2.我們在上面的myclass中加乙個靜態的建構函式我們在來看結果:

public

static

class

myclass

static myclass()

}結果如下:

main execute!

getnow execute!

int: 2009/9/8 15:40:12

getnow execute!

string: 2009/9/8 15:40:15

我們可以發現每次的時間不同了。出現這種現象是由於當類沒有靜態建構函式的時候。在il中該類會被標記為beforefieldinit,這個是由編譯器自動完成的。沒有靜態建構函式的時候初始化在剛進入方法的時候就發生了,而有靜態函式的時候而且我們不需要做任何動作,只要有就可以,這個時候靜態初始化在使用前才發生.我們可以通過看il**來證實這種現象,如下:

3.使用beforefieldinit會提高效能,下面我們就測試下,在測試我們需要計算**執行時間,我們就是用老趙的元件,我稍稍做了一點修改,因為老趙用的win32 api是vista下的,為了以後查詢方便,也貼下**:

using system;

using system.collections.generic;

using system.linq;

using system.text;

using system.diagnostics;

using system.threading;

using system.runtime.interopservices; 

namespace csharpdemo

);} 

public

static

void time(string name, int iteration, action action)

// 3.

stopwatch watch = new

stopwatch();

watch.start();

long cyclecount = getcyclecount();

for (int i = 0; i < iteration; i++) action();

long cpucycles = getcyclecount() - cyclecount;

watch.stop(); 

// 4.

console.foregroundcolor = currentforecolor;

console.writeline("\ttime elapsed:\t" + watch.elapsedmilliseconds.tostring("n0") + "ms");

console.writeline("\tcpu cycles:\t" + cpucycles.tostring("n0")); 

// 5.

for (int i = 0; i <= gc.maxgeneration; i++)

console.writeline();

} private

static

long getcyclecount()

[dllimport("kernel32.dll", setlasterror = true)]

static

extern

bool getthreadtimes(intptr hthread, out

long lpcreationtime,

outlong lpexittime, out

long lpkerneltime, out

long lpusertime); 

[dllimport("kernel32.dll")]

static

extern

intptr getcurrentthread(); }}

下面我們開始測試,我們準備兩個類:

public

class

markbeforefieldinit  

public

class

nobeforefieldinit

}測試**如下:

class

program

);codetimer.time("nobeforefieldinit", iteration, () => ); 

codetimer.time("markbeforefieldinit2", iteration, () => );

codetimer.time("nobeforefieldinit2", iteration, () => );     }}

結果如下:

可以看出beforefieldinit方式的執行速度確實快,但為什麼第二次執行的速度差不多呢?因為經過第一次執行後jit編譯器知道型別的構造器已經被呼叫了,所以第二次執行時不會顯示對建構函式進行呼叫。

生魚片出處:

分類: 

dotnet

標籤: 

beforefieldinit, 

static

關於靜態建構函式

關於靜態建構函式一直有些不特別明白,現在上一次例項,僅供參考。1public class teststaticconstructor211 12public teststaticconstructor 1317 下面是測試 第一種情況 只宣告 static void main string args...

關於c 靜態建構函式

在百科上看到c 的新特性靜態建構函式,其中提到靜態建構函式 不能繼承 今天做了個試驗,發現實際上靜態建構函式是可以繼承的,如下 using system using system.collections.generic using system.linq using system.text usin...

靜態建構函式

1 靜態建構函式既沒有訪問修飾符,也沒有引數。因為是.net呼叫的,所以像public和private等修飾符就沒有意義了。2 是在建立第乙個類例項或任何靜態成員被引用時,net將自動呼叫靜態建構函式來初始化類,也就是說我們無法直接呼叫靜態建構函式,也就無法控制什麼時候執行靜態建構函式了。3 乙個類...