C#构造函数
发布时间:2020-12-15 17:29:34 所属栏目:百科 来源:网络整理
导读:引用类型的实例构造函数不能被继承(不过,可以通过 base 关键字调用父类的构造函数),它负责初始化类型的实例字段。 对于静态字段,由静态构造函数负责。当然,也可以在实例构造函数中为静态成员赋值,但是,当之后更改这个值,再创建一个新的实例时,你会
引用类型的实例构造函数不能被继承(不过,可以通过 base 关键字调用父类的构造函数),它负责初始化类型的实例字段。 对于静态字段,由静态构造函数负责。当然,也可以在实例构造函数中为静态成员赋值,但是,当之后更改这个值,再创建一个新的实例时,你会发现值又被实例构造函数改回去了。 所以,通常在静态构造函数中为静态成员赋值 (因为它只会执行一次)。 如果类型没有定义任何构造函数,C# 会生成一个无参实例构造函数(.ctor),它遍历类 型中所有的成员,并将它们设置为默认值。 可以声明多个不同的构造函数。可以利用 this 关键字来调用其他构造函数。例如: public class AClass { public int i; public static int j; static AClass() { j = 2; Console.WriteLine("静态构造函数"); } public AClass() : this(5) { Console.WriteLine("实例构造函数"); } public AClass(int i) { this.i = i; Console.WriteLine("有参数的实例构造函数"); } }在这个例子中,我们使用下面的代码新建实例: static void Main(string[] args) { var a = new AClass(); Console.WriteLine(a.i); var b = new AClass(10); Console.WriteLine(b.i); Console.ReadKey(); }根据规则,创建 a 时,调用无参的构造函数。但无参的构造函数调用了有参的构造函数,所以,先执行有参的构造函数,将 i 设置为 5,再执行无参的构造函数。 创建 b 则只调用有参的构造函数。最后的输出结果如下图所示。 ![]() 实例构造函数(值类型)如果没有为结构定义构造函数,则 CLR 会生成一个默认的,将其成员初始化为默认值。如果你自定义一个结构体的构造函数,那么必须初始化它的所有成员。结构的自定义构造函数不会被自动调用,所以你要手动地通过 this 来调用。 不能显式地为结构声明无参数的构造函数。 静态构造函数静态构造函数又称类型构造函数,是一个特殊的构造函数,它会在这个类型第一次被实例化或引用任何静态成员之前执行,它具有以下特点:
静态构造函数的目的是为了安全地给静态成员赋值。你可以显式定义静态构造函数为静态成员赋值。 如果什么都不做,它通过元数据得知这个类型有什么静态成员,并在其中初始化这些静态成员为默认值。 静态构造函数默认是没有的。因为它的功能是确定的(为静态字段赋值),而且只运行一次。 所以,它不需要访问修饰符和参数。如果没有显式定义,而且,没有在代码中为静态成员赋值,则 C# 不会自动生成静态构造函数。 例如,为静态成员赋值会导致 IL 岀现 .cctor:
class ExampleRef
.method private hidebysig specialname rtspecialname static void .cctor () cil managed c = "static" ,则不会生成静态构造函数。如果一个类型没有静态字段,那么更不需要自动生成静态构造函数了。当创建第一个实例之前,堆上没有类型对象,所以要调用静态构造函数,引用静态成员之前,堆上也没有类型对象,而静态成员属于类型对象的一部分,所以也要调用静态构造函数。 这两种情况的最终结果,都是堆上最终出现了一个类型对象。因为类型对象只需要建立一次,所以这个静态构造函数也只能运行一次。在这之后,所有的实例对象都指向这个类型对象。 由于 C# 设计成不让外界直接访问静态构造函数,为静态构造函数设置访问修饰符(例如,设置为 public)或传入参数都是没有意义的,因为不可以主动调用。 静态构造函数只负责初始化静态成员,为类型对象的创建而服务,它和类型的实例对象没有关系。 构造函数的执行顺序如果存在一个父类和继承它的子类,那么:
如果父类的实例构造函数是私有的,那么子类构造函数无法通过编译: class Father { public static int i; static Father() { i = 1; Console.WriteLine("父类型的静态构造函数"); } Father() { Console.WriteLine("父类型的实例构造函数"); } } class Son : Father { public static int j; static Son() { j = 1; Console.WriteLine("子类型的静态构造函数"); } Son() { Console.WriteLine("子类型的实例构造函数"); } }上面的代码中父类 Father 的实例构造函数没有访问修饰符,因此,默认会使用 private。 子类的实例构造函数便无法访问父类的实例构造函数,不能通过编译,如下图所示。 ![]() 即使去掉显式定义的 Son 方法,结果也是一样。因此,这可以证明子类的实例构造函数确实会调用父类的实例构造函数。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |