構造函數這玩意也是面試官常常會問到的東西,咱們知道一個類的狀態初始化就全靠它了,下面提幾個小問題。web
Q:我看到Web項目裏面一般都有一個BasePage頁面,其中構造函數裏面作了權限驗證,面試
請問爲何要這麼作。json
A: 既然這麼作了,那麼設計者確定就知道了一個原則就是實例構造器中,父類構造器先於子類執行,那麼這個先執行就可函數
以作不少有意思的事情,好比你說的權限驗證,可能有人會問爲何要先於子類執行,剛纔我也說了,構造函數是用於性能
初始化本類狀態的,這也叫「先掃屋子再請客」的道理吧~,而後風雨兼程的回溯到Object的ctor中。好了,如今來回答spa
你的問題,先把這個問題簡化一下,就不用web項目來演示了。線程
1 public class Program 2 { 3 static void Main(string[] args) 4 { 5 var b = new Bird(); 6 7 Console.Read(); 8 } 9 }10 11 public class Animal12 {13 public Animal()14 {15 Console.WriteLine(running first... i'm animal, all must be running after me.);16 }17 }18 19 public class Bird : Animal20 {21 public Bird()22 {23 Console.WriteLine(the next... i'm a cute bird.);24 }25 }設計
能夠看到,確實Animal於Bird先執行,可能有人會問,那Animal調用的是誰的ctor呢?固然就是Object了,咱們能夠看看IL:orm
Q: 既然你說構造函數用於初始化類的初始狀態,那麼請問下,我如今有一串這樣的cdn
json:{Name:smart,Age:2}。實體類以下圖,請問個人json序列化後,Age=?
1 [Serializable] 2 public class Bird 3 { 4 private string name = smart; 5 6 public string Name 7 { 8 get { return name; } 9 set { name = value; }10 }11 12 private int age = 2;13 14 public int Age15 {16 get { return age; }17 set { age = value; }18 }19 20 public Bird()21 {22 Age = 5;23 }24 }
A:其實這個問題的關鍵在於,反序列化的時候是否會調用構造函數的問題,先來經過Reflector看下源碼,發現並無代碼,以爲
有點小奇怪,就用ILSpy反編譯一下,一樣也沒有代碼,不能否認,底層確定是有代碼執行的,要麼反編譯不出來,要麼clr用了
其餘的方式,反正咱們看不到實現源代碼,若是你們有什麼好意見能夠幫幫我,謝謝了
ILSpy截圖:
據資料說,裏面最後調用了FormatterServices裏面的GetSafeUninitializedObject來分配對象內存,分配完後就不走構造器
了,因此針對這個問題,只能記住了。最後爲了驗證一下,執行完代碼以後確實沒有走構造函數。
Q:我知道引用類型能夠用構造器,那值類型爲何不能定義無參構造器?
A:這個問題問的好,編譯器會根據性能考慮,不會調用值類型的構造函數,即便你強制的new一下也不會執行
1 namespace Sample 2 { 3 public class Program 4 { 5 static void Main(string[] args) 6 { 7 Point point = new Point(); 8 } 9 }10 11 public struct Point12 {13 public int Age;14 }15 }
不過除非你本身顯示定義有參構造函數,並且值類型有個特色就是讀取以前必須初始化,不然會編譯不經過。
Q:請問在類構造函數中能作單例嗎?
A: 能不能作,就要看類構造器的特徵了,咱們知道類構造器跟實例構造器同樣,他是用來初始化靜態字段的,線程
訪問類構造器的時候內部會進行加鎖處理,因此多個線程同時訪問的時候,只會有一個線程執行了類構造器,因此
確實能夠。