构造函数的执行
-
要创建对象的基类部分, 需要隐式的调用基类的无参构造函数
-
继承层次链中的每个类在执行他自己的构造函数体之前执行他的基类构造函数
对象构造的顺序如下
注意
-
禁止在构造函数中调用虚方法
-
在执行基类的构造函数, 基类的虚方法会调用派生类的覆写方法, 但这是执行在派生类的构造函数方法体之前
-
调用会在派生类完群初始化之前传递到派生类
(1)构造函数初始化语句
默认情况下, 在构造对象时, 将调用基类的无参构造器, 但是构造函数可以重载, 所以基类可能有一个以上的构造函数, 如果希望派生类使用一个指定的基类构造函数而不是无参构造函数, 必须在构造函数初始化语句中指定他
访问修饰符 Myclass(参数列表) : 构造函数初始化语句
有两种形式的构造函数初始化语句
A.使用base并指明基类构造器
-
基类构造器初始化语句放在冒号后面, 构造器初始化语句由base和要调用的基类构造器参数列表组成
public MyDerivedClass(int x, string s) : base(s, x) { ... }
-
当声明一个不带构造函数初始化语句的构造函数时候, 他实际上是带有base()构造的初始化函数, 属于隐式调用了
public MyDerivedClass() {} //等价于 public MyDerivedClass() : base() {}
例子
class Base807_1
{
public string FieldBase = "基类字段";
public string IfDerivedCons;
public Base807_1(string ifDerivedCons)
{
IfDerivedCons = ifDerivedCons;
}
public Base807_1()
{
}
public void MethodBase(string value)
{
Console.WriteLine($"基类方法, 输出{ value }");
}
}
class Derived807_1 : Base807_1
{
public string FieldDerived = "派生类字段";
public Derived807_1() : base("派生已生成")
{
}
public void MethodDerived(string value)
{
Console.WriteLine($"派生类方法, 输出{ value }");
}
}
static void Main(string[] args)
{
Derived807_1 derived807_1 = new Derived807_1();
Console.WriteLine(derived807_1.IfDerivedCons); //派生已生成
}
B.使用this并指明使用当前类的构造器
-
这种语句可以让编译器使用当前类中其他构造函数
//让单参数的构造函数使用了同一个类中两个参数的构造函数, 并且为第二个参数提供了一个默认值 public MyClass(int x) : this(x, 1) {} //两个参数的构造函数 public MyClass(int x, int y) {}
1)适用情况1
-
一个类有多个构造器
-
并且他们都需要在对象构造的过程开始时执行一些公共代码
-
可以把公共代码体取出来作为一个构造器
class MyClass807_2_1
{
int MyField;
bool IsNew = false;
public MyClass807_2_1() : this(true)
{
}
public MyClass807_2_1(int myField) : this(true)
{
MyField = myField;
}
private MyClass807_2_1(bool isNew)
{
IsNew = isNew;
}
}
注意:
-
如果声明另一个方法来执行这些公共的初始化, 并让所有构造器来调用这个方法
-
首先编译器会对构造函数做一些优化
-
其次, 如readonly字段(readonly属性不会有这种情况)等, 只能在构造器中初始化, 如果在其他位置(即使这个方法只在构造器中出现), 会编译错误
2)适用情况2
-
如果一个构造器能初始化所有需要初始化的东西, 可以把它声明为public
-
如果一个构造器不能完全初始化一个对象, 必须禁用从类的外部调用构造函数, 声明构造函数为private, 并且让其他构造函数使用它
class MyClass807_2_2
{
readonly int firstVar;
readonly double secoundVar;
public string UserName;
public int UserIdNumber;
//私有构造函数执行其他构造. 函数公有的初始化
private MyClass807_2_2()
{
firstVar = 20;
secoundVar = 30.5;
}
//使用构造函数初始化语句
public MyClass807_2_2(string firstName) : this()
{
UserName = firstName;
UserIdNumber = -1;
}
//使用构造函数初始化语句
public MyClass807_2_2(int idNumber) : this()
{
UserName = "Anonymous";
UserIdNumber = idNumber;
}
}
(2)类访问修饰符
可访问性(accessible)
-
public
-
initernal
1)public
-
标记为public的类可以被系统中任何程序集中的代码访问
-
要使一个类对其他程序集可见, 使用public修饰
2)internal
-
标记为internal的类只能被他自己所在程序集内看到
-
这是默认的可访问级别
-
除非在类的声明中显式指定修饰符public, 否则程序集外部的代码不能访问该类