文章出處

 

   構造函數這玩意也是面試官經常會問到的東西,我們知道一個類的狀態初始化就全靠它了,下面提幾個小問題。

Q:我看到Web項目里面通常都有一個BasePage頁面,其中構造函數里面做了權限驗證,

     請問為什么要這么做。

A:  既然這么做了,那么設計者肯定就知道了一個原則就是實例構造器中,父類構造器先于子類執行,那么這個先執行就可

     以做很多有意思的事情,比如你說的權限驗證,可能有人會問為什么要先于子類執行,剛才我也說了,構造函數是用于

     初始化本類狀態的,這也叫“先掃屋子再請客”的道理吧~,然后風雨兼程的回溯到Object的ctor中。好了,現在來回答

     你的問題,先把這個問題簡化一下,就不用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 Animal
12     {
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 : Animal
20     {
21         public Bird()
22         {
23             Console.WriteLine("the next... i'm a cute bird.");
24         }
25     }

可以看到,確實Animal于Bird先執行,可能有人會問,那Animal調用的是誰的ctor呢?當然就是Object了,我們可以看看IL:

 

Q: 既然你說構造函數用于初始化類的初始狀態,那么請問下,我現在有一串這樣的

    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 Age
15         {
16             get { return age; }
17             set { age = value; }
18         }
19 
20         public Bird()
21         {
22             Age = 5;
23         }
24     }

 

A:其實這個問題的關鍵在于,反序列化的時候是否會調用構造函數的問題,先來通過Reflector看下源碼,發現并沒有代碼,覺得

    有點小奇怪,就用ILSpy反編譯一下,同樣也沒有代碼,不可否認,底層肯定是有代碼執行的,要么反編譯不出來,要么clr用了

    其他的方式,反正我們看不到實現源代碼,如果大家有什么好意見可以幫幫我,謝謝了

 

Reflector截圖:

 

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 Point
12     {
13         public int Age;
14     }
15 }

不過除非你自己顯示定義有參構造函數,而且值類型有個特點就是讀取之前必須初始化,否則會編譯不通過。

 

Q:請問在類構造函數中能做單例嗎?

A: 能不能做,就要看類構造器的特征了,我們知道類構造器跟實例構造器一樣,他是用來初始化靜態字段的,線程

     訪問類構造器的時候內部會進行加鎖處理,所以多個線程同時訪問的時候,只會有一個線程執行了類構造器,所以

     確實可以。

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()