构造函数
1.没有提供构造函数,系统会提供一个无参构造函数。提供了构造函数,系统就不会踢狗默认构造函数。
2.私有构造函数
1 public class MyNumber 2 { 3 private int number; 4 private MyNumber(int number) 5 { 6 this.number = number; 7 } 8 }
仅有私有构造函数,类就不能在外部被实例化。它下下面两种情况下是有用的:
1.类仅当作某些静态成员或静态属性的容器,因此它永远不需要实例化。这样就像静态类一样。
2.希望类仅能通过调用某个静态成员函数来实例化(这就是类工厂方法)。
3.静态构造函数
1 class MyClass 2 { 3 static MyClass() 4 { 5 // 做初始化工作,只能访问类的静态成员 6 } 7 }
静态构造函数没有修饰符,它由.Net运行库调用它,所以public、private等修饰符对它没有意义。
编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性。
静态构造函数不能带参数,一个类只能有一个静态构造函数。
静态构造函数虽然无参,但它与无参实例构造函数并不冲突,尽管它们的参数列表相同。静态构造函数会确保在实例构造函数之前执行。
静态构造函数只能访问类的静态成员,不能访问实例成员。
.Net运行库没有确保什么时候执行静态构造函数,所以不能把要求在某个特定时刻运行的代码放在静态构造函数中。
但是可以确保静态构造函数至多运行一次,即在代码引用类之前调用它。通常在第一次调用类的任何成员之前执行静态构造函数(调用静态成员或实例化之前)。
1 //当调用静态字段时,先执行静态字段的初始化,再执行静态构造函数 2 //当实例化类时,先执行静态字段的初始化,再执行静态构造函数,最后执行实例构造函数 3 public class MyClass 4 { 5 public MyClass() 6 { 7 Console.WriteLine("实例构造函数"); 8 } 9 10 static MyClass() //只会运行一次 11 { 12 Console.WriteLine("静态构造函数"); 13 } 14 15 public static int a = 10; //只会初始化一次 16 17 public static int b = init(); //只会初始化一次 18 19 private static int init() 20 { 21 Console.WriteLine("静态变量 b 初始化"); 22 23 return 30; 24 }
运行结果
4.从构造函数中调用其它构造函数
1 public class BaseCar 2 { 3 public int a; 4 5 public BaseCar(int _a) 6 { 7 this.a = _a; 8 9 Console.WriteLine("BaseCar(int)构造函数"); 10 } 11 } 12 13 public class SonCar : BaseCar 14 { 15 private int b; 16 private int c; 17 18 public SonCar(int _b, int _c) : base(1) //调用父类构造函数的方法 19 { 20 this.b = _b; 21 this.c = _c; 22 } 23 24 public SonCar(int _b) : this(_b, 10) //调用其它构造函数的方法 25 { 26 27 } 28 }
5.在继承关系中的构造函数调用
1.构造子类时,先执行父类构造函数,再执行自类构造函数(仅实例构造函数是这样的,静态构造函数下面介绍)。所以必须保证父类有构造函数可以执行。
当父类有无参构造函数,可以让父类默认使用无参构造函数实例化,不必为父类指定构造函数。
当父类没有无参构造函数,则父类不知道自己改如何初始化,必须为父类显示的指定一个父类已有的构造函数。
1 public class BaseCar 2 { 3 public int a; 4 5 public BaseCar(int _a) //父类提供了自己的构造函数,系统不再为它生成默认无参构造函数了 6 { 7 this.a = _a; 8 9 Console.WriteLine("BaseCar(int)构造函数"); 10 } 11 12 //public BaseCar() 13 //{ 14 // 自己提供的无参构造函数和系统默认的无参构造函数作用相同 15 //} 16 } 17 18 public class SonCar : BaseCar 19 { 20 private int b; 21 private int c; 22 23 public SonCar(int _b, int _c) // 程序不能通过编译 当没有指定父类以哪个构造函数实例化时,默认使用无参构造函数,但是此时父类却没有无参构造函数 24 { 25 this.b = _b; 26 this.c = _c; 27 } 28 29 public SonCar(int _b) : base(1) // 正确 当父类没有无参构造函数时,就需要为父类指定一个父类已经存在的构造函数 30 { 31 32 } 33 }
2.当继承关系中,存在静态构造函数时,执行顺序是怎么样的呢?
子类静态字段 => 子类静态构造函数 => 父类静态子弹 => 父类静态构造函数 => 父类实例构造函数 => 子类实例构造函数
1 public class BaseCar 2 { 3 public static int a = Init(); 4 5 public BaseCar() 6 { 7 Console.WriteLine("BaseCar()实例构造函数"); 8 } 9 10 static BaseCar() 11 { 12 Console.WriteLine("BaseCar静态构造函数"); 13 } 14 15 private static int Init() 16 { 17 Console.WriteLine("BaseCar初始化静态字段"); 18 return 10; 19 } 20 } 21 22 public class SonCar : BaseCar 23 { 24 public static int b = Init(); 25 26 public SonCar() 27 { 28 Console.WriteLine("SonCar()实例构造函数"); 29 } 30 31 static SonCar() 32 { 33 Console.WriteLine("SonCar静态构造函数"); 34 } 35 36 private static int Init() 37 { 38 Console.WriteLine("SonCar初始化静态字段"); 39 return 20; 40 } 41 }
运行结果