构造函数这玩意也是面试官常常会问到的东西,咱们知道一个类的状态初始化就全靠它了,下面提几个小问题。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 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: 既然你说构造函数用于初始化类的初始状态,那么请问下,我如今有一串这样的3d
json:{"Name":"smart","Age":2}。实体类以下图,请问个人json序列化后,Age=?code
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: 能不能作,就要看类构造器的特征了,咱们知道类构造器跟实例构造器同样,他是用来初始化静态字段的,线程
访问类构造器的时候内部会进行加锁处理,因此多个线程同时访问的时候,只会有一个线程执行了类构造器,因此
确实能够。