<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      .ctor,.cctor 以及 對象的構(gòu)造過程

      .ctor:

      簡述:構(gòu)造函數(shù),在類被實例化時,它會被自動調(diào)用。

      當(dāng)C#的類被編譯后,在IL代碼中會出現(xiàn)一個名為.ctor的方法,它就是我們的構(gòu)造函數(shù),對應(yīng)C#中的構(gòu)造函數(shù)。且看下面的代碼:

      public class Class1
      {
          
      private string name;
          
      private int age;
      }


      類Class1中沒有顯示的構(gòu)造函數(shù),只有兩字段,現(xiàn)在用ILDasm.exe打開編譯后生成的exe文件,會看到:



      可以看到這里有個.ctor,我們沒有定義構(gòu)造函數(shù),但這里卻出現(xiàn)了.ctor,這就說明了:

      當(dāng)沒有顯示定義構(gòu)造函數(shù)時,會自動生成一個構(gòu)造函數(shù),它沒有參數(shù),沒有返回值。

      那我們來看看這個.ctor都干了什么吧,雙擊.ctor打開,在彈出的窗口中可以找到下面的幾行代碼:

       IL_0000: ldarg.0

       IL_0001: call       instance void [mscorlib]System.Object::.ctor()

       IL_0006: ret

      上面就是這個.ctor的方法體,看上面的紅色行,從字面上可以看出,它是調(diào)用(call)了一個類型為System.Object的實例的.ctor()方法,從這就可以證明:

      當(dāng)一個類沒有顯示聲明繼承于其它某個類時,它將默認(rèn)繼承自System.Object,并且,在類的構(gòu)造函數(shù)中將會調(diào)用其基類的構(gòu)造方法(.ctor)。

      現(xiàn)在對上面的程序小改一下,在聲明name時對其初始化:

      public class Class1
      {
         
      private string name = "Lin";
         
      private int age;
      }

      再用ILDasm打開生成的exe文件,打開.ctor,里面有這么幾行:

        IL_0000: ldarg.0

       IL_0001: ldstr      "Lin"

       IL_0006: stfld      string ConsoleApplication1.Class1::name

       IL_000b: ldarg.0

       IL_000c: call       instance void [mscorlib]System.Object::.ctor()

       IL_0011: nop

      這個跟剛才的相比,多出了紅色的那兩行,這兩行出現(xiàn)在“調(diào)用System.Object的構(gòu)造方法”之前,這說明:

      如果在字段聲明的同時對其初始化,那么在編譯后,賦值過程將被放到構(gòu)造方法.ctor中,并且在調(diào)用其基類的構(gòu)造方法之前進行。

      現(xiàn)在給上面的C#程序顯式加上一個構(gòu)造方法,它接受兩個參數(shù):

      public class Class1
      {
              
      private string name = "Lin";
              
      private int age;

              
      public Class1(string name, int age)
              
      {
                  
      this.name = name;
                  
      this.age = age;
              }

      }

      再用ILDasm打開exe時,會發(fā)現(xiàn)有了點變化:

      這里的.ctor帶了兩參數(shù),一個string類型,一個int32類型,而剛才的無參無返回值的.ctor不見了,這也證明了:

      如果類中有顯式定義構(gòu)造方法,那么就不會再自動生成一個無參數(shù)無返回值的默認(rèn)構(gòu)造方法。

      打開.ctor,會看到其中有這么幾行:

       IL_0000:  ldarg.0

       IL_0001: ldstr      "Lin"

       IL_0006: stfld      string ConsoleApplication1.Class1::name

       IL_000b: ldarg.0

       IL_000c: call       instance void [mscorlib]System.Object::.ctor()

       IL_0011: nop

       IL_0012: nop

       IL_0013: ldarg.0

       IL_0014: ldarg.1

       IL_0015: stfld      string ConsoleApplication1.Class1::name

       IL_001a: ldarg.0

       IL_001b: ldarg.2

       IL_001c: stfld      int32 ConsoleApplication1.Class1::age

       IL_0021: nop

      從上面紅色標(biāo)識的代碼的順序中,我們可以進一步得到:

      如果在聲明字段時同時對其賦值,那么這個賦值過程將在類型的構(gòu)造方法(.ctor)中最先執(zhí)行,然后再執(zhí)行其基類的構(gòu)造方法,最后才輪到我們顯示定義的構(gòu)造方法體中代碼。

      .cctor

      簡述:類型初始化器,是一個靜態(tài)方法,無參數(shù)無返回值,不能直接調(diào)用,最多只有一個

      我們現(xiàn)在先給剛才的代碼加上一個靜態(tài)字段:
      public class Class1
      {
              
      private string name = "Lin";
              
      public static int count = 50;
              
      private int age;

              
      public Class1(string name, int age)
              
      {
                  
      this.name = name;
                  
      this.age = age;
              }

      }


      再來打開ILDasm來看看:

      發(fā)現(xiàn)這里多了一個.cctor,它就是類型初始化器,打開它,會看到其中有一句:

        IL_0000: ldc.i4.s   50

       IL_0002: stsfld     int32 ConsoleApplication1.Class1::count

      它對靜態(tài)字段count進行了賦值,值是50,那么,是.cctor先調(diào)用還是.ctor先調(diào)用呢?當(dāng)然是.cctor,它是為初始化類型而生的,專搞靜態(tài)的東東,而.ctor是構(gòu)造方法,當(dāng)然.cctor要先調(diào)用了。

      現(xiàn)在顯示加上一個.cctor,在C#中就是加個靜態(tài)構(gòu)造函數(shù),我們不能為其指定訪問修飾符(否則編譯就會報錯):

      public class Class1
      {
              
      private string name = "Lin";
              
      public static int count = 50;
              
      private int age;

              
      static Class1()
              
      {
                  count 
      = 100;
              }


              
      public Class1(string name, int age)
              
      {
                  
      this.name = name;
                  
      this.age = age;
              }

      }

      再來看看現(xiàn)在ILDasm下的.cctor,其中有幾行: 

       IL_0000: ldc.i4.s   50

       IL_0002: stsfld     int32 ConsoleApplication1.Class1::count

       IL_0007: nop

       IL_0008: ldc.i4.s   100

       IL_000a: stsfld     int32 ConsoleApplication1.Class1::count

      可以看到:
      如果在聲明靜態(tài)字段時同時對其賦值,它在編譯后會被搬到.cctor中,并且是放在前面,然后才到顯式定義的靜態(tài)構(gòu)造方法體中的代碼,也就是說count在這里會被賦值兩次,第一次50,第二次100。

      在繼承中對象構(gòu)造過程

      看下面這段程序:

          public class A
          
      {
              
      public int x = 1;
              
      public A() { m1(); }
              
      public void m1() { }
          }


          
      public class B : A
          
      {
              
      public int y = 2;
              
      public static string sb = "B";
              
      public B() { m2(); }
              
      public void m2() { }
          }


          
      public class C : B
          
      {
              
      public int z = 3;
              
      public static string sc = "C";
              
      public C() { m3(); }
              
      public void m3() { }
          }


      編譯后用ILDasm打開生成的exe文件:


      可以看到三者都有一個.ctor,B、C中有.cctor,而A沒有,打開B,C的.cctor,可以看到它們都負(fù)責(zé)初始化自己的靜態(tài)字段,現(xiàn)在主要來看它們的.ctor。

      先看類C的.ctor:

       IL_0001: ldc.i4.3

       IL_0002: stfld      int32 ConsoleApplication1.C::z

       IL_0007: ldarg.0

       IL_0008: call       instance void ConsoleApplication1.B::.ctor()

       IL_000d: nop

       IL_000e: nop

       IL_000f: ldarg.0

       IL_0010: call       instance void ConsoleApplication1.C::m3()

      可以看到:
      在C被實例化時,它最先初始化在聲明時同時賦值的字段(非靜態(tài)),此處是將3賦給z,然后它會調(diào)用其基類的.ctor(),然后再調(diào)用自己的實例方法m3(),值得注意的是,在執(zhí)行顯式定義的構(gòu)造方法體中的代碼前,會先調(diào)用其基類的構(gòu)造方法(創(chuàng)建基類的實例)。

      再來看類B的.ctor(): 

       IL_0001: ldc.i4.2

       IL_0002: stfld      int32 ConsoleApplication1.B::y

       IL_0007: ldarg.0

       IL_0008: call       instance void ConsoleApplication1.A::.ctor()

       IL_000d: nop

       IL_000e: nop

       IL_000f: ldarg.0

       IL_0010: call       instance void ConsoleApplication1.B::m2()

      同樣,我們可以看到,在實例化B時,它會先把2賦給自己的y,然后再調(diào)用基類A的構(gòu)造方法,最后再調(diào)用自己的實例方法m2()。

      那A的.ctor()就不再看了,可以猜到它一定是在做這樣的事:
      1、 將1賦給實例的x字段;
      2、 調(diào)用基類System.Object的構(gòu)造方法.ctor來創(chuàng)建基類的實例;
      3、 調(diào)用實例方法m1();

      總結(jié)

      1、.ctor是構(gòu)造方法;
      2、.cctor是類型初始化器,在C#中也就是靜態(tài)構(gòu)造函數(shù);
      3、當(dāng)類C實例化時,會先對聲明時就進行賦值的字段賦值,然后調(diào)用基類的構(gòu)造函數(shù),基類再以同樣的方法構(gòu)造自己,一直到頂層的System.Object,然后再回來執(zhí)行C的顯式構(gòu)造方法中的代碼,就是這么一個遞歸的過程。

      參考資料

      1、《Essential .NET》 Volume 1

      posted @ 2008-05-18 03:38  水言木  閱讀(8445)  評論(8)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品国男人在线视频| 欧美交a欧美精品喷水| 毛片亚洲AV无码精品国产午夜| 男女性高爱潮免费网站| 中文国产日韩欧美二视频| 日本高清免费不卡视频| 久久精品国产再热青青青| 激情综合网激情五月俺也去| 亚洲国产午夜精品福利| 一本高清码二区三区不卡| 亚洲一二三四区中文字幕| 亚洲国产成人精品av区按摩| 亚洲综合伊人久久大杳蕉| 国产成人亚洲日韩欧美| 荣成市| 日韩精品一区二区三区人| 精品人妻二区中文字幕| 亚洲高清最新AV网站| 国产高清视频一区二区三区| 一区二区三区av天堂| 国产短视频一区二区三区| 在线中文字幕国产精品| 亚洲香蕉网久久综合影视| 国产av亚洲精品ai换脸电影 | 成人3D动漫一区二区三区| 国产对白老熟女正在播放| 久热这里只有精品视频3| 久久国产精品精品国产色| 国产精品女生自拍第一区 | 亚洲爆乳成av人在线视菜奈实| 新源县| 中文字幕av一区二区| 精品人妻少妇一区二区三区在线| 人妻有码中文字幕在线| 国产精品一区二区三区黄色| 一区二区三区人妻无码| 日韩有码中文字幕一区二区| 2020年最新国产精品正在播放| 97久久精品无码一区二区| 久久久久久av无码免费网站| 欧美猛少妇色xxxxx猛叫|