再過幾個小時,就要回家過春節了,今天說些簡單點的東西,大家在看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...