C 中為什麼會出現空靜態構造方法的寫法

2022-03-10 17:52:53 字數 1884 閱讀 5710

再過幾個小時,就要回家過春節了,今天說些簡單點的東西,大家在看c#**的時候,一定會對這樣的寫法非常迷茫:在乙個類中會出現乙個空的靜態構造方法。這不是多此一舉嗎,這樣做的目的是什麼?今天我就來說說這個內容。

前段時間,小夥伴遇到乙個問題,百思不得其解,我先來模擬下這個問題:

class program

}

public class mytest

}

**比較簡單,就是有兩個類,乙個是主程式入口,乙個是業務類,在業務類裡面,定義了乙個static的變數,給它賦上乙個方法,方法中讀取了配置中心的內容,並且返回,那麼這個static的變數的值就是配置中心的內容了,在主程式入口,一開始就初始化了配置中心,然後訪問在業務類中的靜態變數,並且利用這個值,做一些後續操作。

我們先不管這樣的邏輯是否合理,就只看能否正常執行。

這樣的**看上去並沒有什麼問題,但是讓人不解的是,丟擲了異常,內容是「配置中心未初始化」,小夥伴懵了,明明一開始就初始了配置中心啊,為什麼讀取配置中心內容的時候,還會出現這樣的異常呢。

我一看,立刻懂了,於是我在業務類中,加了乙個靜態的構造方法,如下所示:

public class mytest

static mytest()

}

一切都好了。

我加了乙個空的靜態方法,注意是空的,為什麼加了乙個空的靜態方法可以解決問題呢?我們再來做個試驗把:

class program

}

public class mytest

}

讓我們想想會輸出什麼?這還不簡單,當然是 初始化配置中心 進到了getconfig方法 配置中心的內容,但是,當我們執行:

你會發現,奇怪的事情出現了,第乙個輸出的竟然是 進到了「getconfig方法」。

輸出竟然被改變了。

這就是解釋了為什麼小夥伴一開始的**會出現問題的原因,因為程式一上來,還沒有執行 初始化配置中心呢,直接讀取了配置中心的內容,而我加上的空靜態構造方法,就改變了**的執行順序,是不是很神奇。

我們在用ilspy看下il**,當類中沒有靜態構造方法的時候:

il**有乙個標記:beforefieldinit

當類中的靜態構造方法的時候:

beforefieldinit標記消失了。

我們來做乙個總結,當乙個類中沒有靜態構造方法的時候,il會有beforefieldinit標記,程式一執行,就會初始化靜態字段,當乙個類中有靜態構造方法的時候,il沒有beforefieldinit標記,程式一開始就不會初始化靜態字段,而是用到這個類了,才初始化靜態字段。

現在我們可以解釋為什麼在餓漢式的單例模式中,經常會看到空的靜態構造方法了,因為不想讓程式在一開始的時候就初始化這個單例物件,而是用到了才去初始化,相當於懶載入,其實這也是一種優化,如果程式執行後,長時間沒有使用到這個單例物件,而一開始程式就把單例物件載入到記憶體中去了,也是一種浪費。

這篇的內容到這裡就結束了,哈哈,馬上就解放啦。

訊號處理中為什麼會出現負頻率

在自然界我們所能夠接觸到的訊號都是實訊號,那麼訊號的頻率肯定都是正的呀,但是在訊號處理過程中進行傅利葉變換後通常會出現負頻率呢?出現這個疑問的最根本原因是沒有搞清楚這兩個頻率之間的關係,確切的來說是此頻率非彼頻率,買個關子,下面開始解釋 就拿週期訊號f x 的傅利葉變換說吧,週期訊號的傅利葉級數展開...

為什麼會出現 符號,c 6 0才出現的新特性

目錄 為什麼會出現符號c60才出現的新特性 c60為了改善stringformat使用的不方便才有了 格式化 csharp view plain copy print?var s string fromat 12,23,12 23 用起來必須輸入string.fromat,使用佔位符,必須按照0,1...

為什麼會出現 符號,c 6 0才出現的新特性

目錄 為什麼會出現符號c60才出現的新特性 c60為了改善stringformat使用的不方便才有了 格式化 csharp view plain copy print var s string.fromat 12,23,12 23 用起來必須輸入string.fromat,使用佔位符,必須按照0,1...