程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 基類構造函數和初始化器的執行順序

基類構造函數和初始化器的執行順序

編輯:關於.NET

標題比較抽象,所以我寫了一個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#編譯器為什麼這樣設計,我也沒有想到太合理的原因,大家有什麼看法呢?

請大家多多指教啊!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved