zoukankan      html  css  js  c++  java
  • 基类构造函数和初始化器的执行顺序!

    标题比较抽象,所以我写了一个Demo来说明问题:
            public class A
            {
                public A()
                {
                    Console.WriteLine("A的构造函数被调用");
                }
            }
            public class B : A
            {
                private X x = new X();  //初始化器
            }
            public class X
            {
                public X()
                {
                    Console.WriteLine("X的构造函数调用");
                }
            }
            static void Main(string[] args)
            {
                B b = new B();
             }
    在调用子类的构造函数之前,会先调用基类的构造函数,那初始化器和基类的构造函数到底谁先执行呢?
    因为初始化代码会在构造函数中的代码之前执行,所以我过去错误的认为:
            public class B : A
            {
                private X x = new X();  //初始化器
            }
    等价于:
            public class B : A
            {
                private X x;
                public B()
                {
                     x=new X();
                 }
            }
    所以我也错误的认为基类的构造函数是在子类的初始化器之前执行的,上面的Demo执行的结果刚好相反,是:
    X的构造函数调用
    A的构造函数被调用

    这表明子类的构造器先执行了,让我们看看生成的构造函数的IL代码:
            public class B:A
            {
                private X x;
                public B()
                {
                    x = new X();
                }
            }
    生成的构造函数的IL代码是这样的:
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // 代码大小       21 (0x15)
      .maxstack  8
      IL_0000:  ldarg.0
      IL_0001:  call       instance void ConsoleApplication1.Program/A::.ctor()
      IL_0006:  nop
      IL_0007:  nop
      IL_0008:  ldarg.0
      IL_0009:  newobj     instance void ConsoleApplication1.Program/X::.ctor()
      IL_000e:  stfld      class ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
      IL_0013:  nop
      IL_0014:  ret
    } // end of method B::.ctor
    从代码可以看出是先调用基类的构造函数的!
            public class B : A
            {
                private X x = new X();
            }
    生成的构造函数的IL代码是这样的:
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // 代码大小       19 (0x13)
      .maxstack  8
      IL_0000:  ldarg.0
      IL_0001:  newobj     instance void ConsoleApplication1.Program/X::.ctor()
      IL_0006:  stfld      class ConsoleApplication1.Program/X ConsoleApplication1.Program/B::x
      IL_000b:  ldarg.0
      IL_000c:  call       instance void ConsoleApplication1.Program/A::.ctor()
      IL_0011:  nop
      IL_0012:  ret
    } // end of method B::.ctor
    可以看出是先调用初始化器的代码,然后再调用基类构造函数的!可见使用初始化器和不使用初始化器还是有区别的,主要区别是基类构造函数的调用顺序不同!
    C#编译器为什么这样设计,我也没有想到太合理的原因,大家有什么看法呢?
    请大家多多指教啊!
  • 相关阅读:
    Apollo,Python,Delphi与Oracle之间的神话关系
    Delphi语言获得生命的原因和过程
    cocos2d(x) HTML label ;CCHTML CCHTMLLabel
    不重启使XP环境变量生效
    对当下纷繁乱世的思考框架(核心与边缘,时间与成本)
    晚明一出,明朝不必再穿越了
    常用的Linux终端
    如何发布使用LGPL版Qt的商业软件
    如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4
    文明之火熊熊燃烧,灼热乃至引燃了周边霉湿的柴草
  • 原文地址:https://www.cnblogs.com/xuefeng1982/p/1645018.html
Copyright © 2011-2022 走看看