C# 类 构造函数的执行顺序

  

namespace Temp
{
    class Program
    {
        static void Main(string[] args)
        {
            Class1 c = new Class1();
        }
    }

    class BaseClass
    {
        int z = 3;

        public BaseClass()
        {
            Demo();
        }

        public virtual void Demo()
        {
            Console.WriteLine("BaseClass.Demo");
        }
    }

    class Class1 : BaseClass
    {
        int x = 1;
        int y;

        public Class1()
        {
            y = 2;
        }

        public override void Demo()
        {
            Console.WriteLine(x + y);
        }
    }
}




 

整个过程:

  1. 黄色光标进入 Class1 类时跳入了第一句 int x = 1;
  2. 黄色光标跳过第二句 int y 指向 Class1 的构造函数;
  3. 在执行构造函数的代码块之前跳入了父类,黄色光标指向父类 BaseClass 的 int z = 3 语句;
  4. 黄色光标指向 BaseClass 的构造函数;
  5. 黄色光标指向构造函数内的 MethodA() 调用;
  6. 黄色光标跳向子类 Class1 重写的方法 MethodA();
  7. 查看两个字段发现 x=1, y=0;
  8. 黄色光标指向 Console 语句;
  9. 黄色光标从父类构造函数的 MethodA() 调用中跳出;
  10. 黄色光标从父类构造函数跳出,并再次指向子类构造函数,执行完其中的代码块;
  11. 直至执行完毕。

这里说明了几个顺序问题:

  1. 对于直接赋值的字段的赋值步骤是在构造函数之前执行,子类字段的赋值是在父类的字段赋值之前;
  2. 对于字段的内存分配、初始化等步骤是在我们所能看到的黄色光标进入 Class1 类的步骤之前;
  3. 执行构造函数前会首先执行父类的构造函数;
  4. 执行构造函数时 CLR 已能识别方法的覆写情况,表明方法的加载过程是在对字段的赋值步骤之前;
  5. int 类型的字段在分配内存、初始化阶段已默认赋了 0 值(仅限字段中的 int,方法中的int变量并非如此)。

总结:当执行 new 语句时,发生了以下几件事情(更细的情形本文暂不探讨):

  1. 为字段分配内存并进行初始化;
  2. 如果类是第一次加载(即系统中从未创建类的其它对象,或者曾经创建但因不再有引用而被 GC 全部回收),则 Copy 其实例方法至方法表;
  3. 为类中需要直接赋值的字段赋值;
  4. 执行构造函数。

PS:https://www.cnblogs.com/flaugh/archive/2010/10/12/1849018.html转载

 

posted @ 2021-02-04 16:04  物极必反iii  阅读(535)  评论(0)    收藏  举报