一道关于静态构造函数与抽象类构造函数的面试题引发的思考
前段时间找工作,去面试碰到了两道关于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!
哎,丢人丢大了,非常简单的两道题目,在此写下来,觉得有用的拿走吧,觉得没用的就嘲笑我呗!!!