构造函数是一种特殊的函数,该函数没有返回值,且名称必须和类的名称一致。更重要的是构造函数不可以被继承。
当一个类没有定义任何的构造函数时,编译器会给这个类一个默认的构造函数。
默认的构造函数没有参数,且是public访问修饰。
构造函数是类最先调用的函数。又被分为实例构造函数和静态构造函数。
静态构造函数(也叫类型构造函数):一个类只能有一个静态构造函数。该构造函数没有访问修饰,没有参数。
静态构造函数在整个运行中,只被访问一次,那是在对该类第一次实例化或第一次调用该类的静态成员是访问静态构造函数。
所以说静态构造函数比实例构造函数(如果存在实例构造函数)调用得更早。
实例构造函数可以有多种访问修饰,可以有参数(也就是说可以有多个实例构造函数),实例构造函数是当用户实例化类的时候,也就是在用new构造类的时候调用。
1 public class Space 2 { 34 public static void Main(string[] args)5 { 6 Order order1 = new Order();7 System.Threading.Thread.Sleep(500);8 Order order2 = new Order();9 System.Threading.Thread.Sleep(500);10 Order order3 = new Order();11 }1213 } 14 15 public class Order 16 { 1718 static Order()19 { 20 System.Console.WriteLine("Static Order()");21 }22 public Order()23 { 24 System.Console.WriteLine("Order()");25 }26 } 运行上面的代码,你可以发现,System.Console.WriteLine("Static Order()");只被调用了一次。而System.Console.WriteLine("Order()");在每次new的时候都被调用。
构造函数虽然不能被继承,也不能在非New的时候被调用,但是构造函数却可以调用基类的构造函数和当前类的其他构造函数(当然是指实例构造函数了,因为静态构造函数当前类只有一个,静态构造函数也不能访问基类的构造函数)
基类的构造函数通过base关键字访问。当前实例的其他构造函数通过this访问。且base和this都比当前构造函数优先。
请运行和分析一下下面的代码
1 public class Space 2 { 34 public static void Main(string[] args)5 { 6 ShipOrder ShipOrder1 = new ShipOrder();7 System.Console.WriteLine("----------------");8 System.Threading.Thread.Sleep(500);9 ShipOrder ShipOrder2 = new ShipOrder();10 System.Console.WriteLine("----------------");11 System.Threading.Thread.Sleep(500);12 ShipOrder ShipOrder3 = new ShipOrder();13 }1415 } 16 17 public class Order 18 { 1920 static Order()21 { 22 System.Console.WriteLine("Static Order()");23 }24 public Order()25 { 26 System.Console.WriteLine("Order()");27 }2829 public string Number;30 } 31 32 public class ShipOrder : Order 33 { 3435 public ShipOrder(string number)36 : base()37 { 38 System.Console.WriteLine("ShipOrder(string)");39 }4041 public ShipOrder()42 : this("12-123")43 { 44 System.Console.WriteLine("ShipOrder()");45 }464748 } 我们实例化ShipOrder(无参构造函数)时,该构造函数要求先调用一个含string的有参构造函数(第42行)。而有参构造函数却要先调用基类Order的构造函数(第36行)。而基类Order有静态构造函数,静态构造函数优先,所以
运行的结果是
Static Order()
Order()
ShipOrder(string)
ShipOrder()
----------------
Order()
ShipOrder(string)
ShipOrder()
----------------
Order()
ShipOrder(string)
ShipOrder()
有意思的是我们修改一下代码
1 public class Space 2 { 34 public static void Main(string[] args)5 { 6 ShipOrder ShipOrder1 = new ShipOrder();7 System.Console.WriteLine("----------------");8 System.Threading.Thread.Sleep(500);9 ShipOrder ShipOrder2 = new ShipOrder();10 System.Console.WriteLine("----------------");11 System.Threading.Thread.Sleep(500);12 ShipOrder ShipOrder3 = new ShipOrder();13 }1415 } 16 17 public class Order 18 { 1920 static Order()21 { 22 System.Console.WriteLine("Static Order()");23 }24 public Order()25 { 26 System.Console.WriteLine("Order()");27 }2829 public string Number;30 } 31 32 public class ShipOrder : Order 33 { 3435 public ShipOrder(string number)36 //: base()37 { 38 System.Console.WriteLine("ShipOrder(string)");39 }4041 public ShipOrder()42 : this("12-123")43 { 44 System.Console.WriteLine("ShipOrder()");45 }4647 } 注意第36行,现在的运行结果是什么样的呢?
结果和刚才一样,因此我们证明,无论怎么样,在构造子类前,编译器会先构造基类。
ok,最后我们看一下,下面的运行结果你认为是什么呢?
1 public class Hello 2 { 3 private static int n=20;4 public int m=10;5 static Hello()6 { System.Console.WriteLine(n); }7 public Hello():this(15)8 { System.Console.WriteLine(this.m);9 System.Console.WriteLine(n);10 System.Console.ReadLine(); }11 public Hello(int i ):base()12 { System.Console.WriteLine(i); }13 public static void Main(string[] args)14 { new Hello(); }15} 16