.net类的初始化机制,顺序,内存分配

本文探讨了.NET类的初始化顺序,包括静态和实例字段的初始化、静态构造函数的调用,以及在继承链中的执行流程。此外,还提到了内存分配机制,从对象创建到类型对象的构建,再到实例字段的构造,详细阐述了类实例化的过程。在多重继承和静态方法调用的情景下,初始化行为也进行了说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于类的初始化,久不温习,都有点忘记了,查了些资料,留此以作备忘:

类成员的初始化顺序, 举例 ChildClass从ParentClass继承而来

1.  初始化ChildClass的静态字段(按声明顺序)
2.  初始化ChildClass的静态构造函数
3.  初始化ChildClass的实例字段
4.  调用ChildClass的构造函数,并在此中断, 调用ParentClass的构造函数, 导致ParentClass开始初始化
5.  初始化ParentClass的静态字段
6.  初始化ParentClass的静态构造函数
7.  初始化ParentClass的实例字段
8.  调用ParentClass的实例构造函数
9.  ParentClass初始化完毕, 调用ChildClass的构造函数,完成创建

如果多重继承,将按上面方式展开,静态构造函数和静态字段都只构造一次.

如果类没有实例化以前,调用该类的静态方法(字段),会引起类的静态字段实例化, 调用静态构造函数. 以后再实例化此类的时候,不再重新实例化静态字段和静态构造函数

这种初始化顺序是由内存分配机制决定的,如我们调用MyClass myClass = new MyClass(), 其产生对象如下:

1. 计算该类中定义的所有实例字段的size和两个附加对象(type handler(类对象的指针)和syncBlockIndex(指向一块用来管理对象同步的内存))的size并一直递归到object对象,得到其需要分配内存大小, 看剩余内存是否够分配此对象, 不够会导致垃圾回收.
2. 首先构造MyClass的type对象,type对象包括静态字段和方法表,将其分配在托管堆的loader堆上,注意此对象将不会被GC自动回收, 其生命周期是从创建到AppDomain卸载.
3. 构造MyClass的实例字段,构造附加type handler并指向type对象, 构造SyncBlockIndex并指向同步内存. 
4. 调用MyClass构造函数,此时会引起其父类初始化, 父类初始化循环上述过程,直至object对象完成创建, 再返回执行子类构造函数直至MyClass, 创建MyClass完成后, 返回其内存地址, 赋值给MyClass的this,并将其引用传给栈上声明的myClass.

    class ParentClass
    {
        // 静态变量       
        public static DisplayClass p_StaticField = new DisplayClass("父类--静态变量");
        // 变量       
        public DisplayClass p_Field = new DisplayClass("父类--变量");
        // 静态初始化块       
        static ParentClass() { Console.WriteLine("父类--静态初始化块"); }
        // 构造器       
        public ParentClass() { Console.WriteLine("父类--构造器"); }
    }

    class ChildClass : ParentClass
    {
        // 静态变量       
        public static DisplayClass s_StaticField = new DisplayClass("子类--静态变量");
        // 变量       
        public DisplayClass s_Field = new DisplayClass("子类--变量");
        // 静态初始化块       
        static ChildClass() { Console.WriteLine("子类--静态初始化块"); }
        // 构造器       
        public ChildClass() { Console.WriteLine("子类--构造器"); }
        // 程序入口       
        public static void Main() 
        {
            new ChildClass(); 
        }
    }

    class DisplayClass
    {
        public DisplayClass(string message)
        {
            Console.WriteLine(message);
        }
    }

执行结果:


C#中执行结果与java完全不一样,java中类似代码执行结果如下:



评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值