前段時間找工作,去面試碰到了兩道關於C#構造函數的題目,首先來看靜態構造函數的題目如下(原題不 是如此,但類似,因為實在記不住那題目的樣子了,第二題也是):
class Base { static Base() { Console.WriteLine("Static Base"); } public Base() { Console.WriteLine("Base"); } }
問當創建Base的實例時產生什麼輸出?我咋一看,挺簡單,我當時認為:構造函數為類的成員 ,實例化自然是只用到了實例成員,關靜態成員鳥事,什麼爛題目。於是寫“Base”。寫歸寫,後來還是有點 懷疑(對於不完全確認的程序我還是喜歡自己編碼驗證),於是乎發現真的是我錯了。去new一個類的實例時 確實先調用了靜態構造函數(如果存在),那麼到底什麼時候調用呢,是在聲明的時候(Base b = null;)還 是實例化的時候(b = new Base();)調用呢?我覺得是是聲明的時候,然後接著又發現了自己還是錯了。啰嗦有 點多了,大家可以上MSDN查看關於靜態構造函數的官方說明:http://msdn.microsoft.com/zh- cn/library/k9x6w0hc(v=vs.80).aspx
接下來我還有一個疑問,就是在繼承關系中這個靜態構造函數的 父子類調用情況如何呢?我不敢妄下結論了,老錯。
繼續編寫代碼添加一個子類
class Child : Base { static Child() { Console.WriteLine("Static Child"); } public Child() { Console.WriteLine("Child"); } }
這時候我去new一個Child對象,輸出如下:
我去,跟實例構造函數的調用 順序剛好相反,其所有構造函數的調用順序為:本身靜態構造函數 -> 父類靜態構造函數 -> 父類實例 構造函數 -> 本身實例構造函數。
這個東西貌似實用性不是太大,但是在一個含有靜態成員的類裡 面,還是可以有不少的用武之地的。
好,接下來看另一道題,代碼如下
abstract class A { public A() { PrintFields(); } public virtual void PrintFields() { } } class B : A { int x = 1; int y; public B() { y = -1; } public override void PrintFields() { Console.WriteLine("x={0},y={1}", x, y); } }
很常見的一道面試題,熟悉繼承的童鞋一眼就能看出來結果啦,但是我當時碰到兩道一樣的題 目,第一道老老實實寫了答案了,然後還有一道是重復的,草泥馬,老子再仔細看下,哦,後面這道是抽象類 ,我一想抽象類不能實例化,構造函數?也不能有的吧,當時立馬寫下編譯器報錯抽象類不能包含構造函數。 後來驗證了,我大錯特錯,抽象類有構造函數且在繼承中其作用情況與非抽象類一樣,OH,this is shit!
哎,丟人丟大了,非常簡單的兩道題目,在此寫下來,覺得有用的拿走吧,覺得沒用的就嘲笑我呗! !!