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

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

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

      《CLR Via C# 第3版》筆記之(四) - 類中字段的默認(rèn)賦值

      在C#中,除了可以在類的構(gòu)造函數(shù)中初始化私有字段的值,還可以在私有字段定義的地方進(jìn)行初始化(即默認(rèn)賦值)。下面討論默認(rèn)賦值和在構(gòu)造函數(shù)中賦值的區(qū)別,以便更好的在代碼中使用這兩種賦值。

      主要內(nèi)容:

      • 對(duì)代碼生成的影響
      • 對(duì)代碼執(zhí)行的影響

      1. 對(duì)代碼生成的影響

      首先構(gòu)造兩個(gè)Class,其中ClassA使用默認(rèn)賦值的方式,ClassB使用構(gòu)造函數(shù)賦值的方式。

      代碼如下:

          public class ClassA
          {
              private Int32 a = 123;
              private String b = "abc";
              private Object c = new object();
      
              public ClassA()
              {
              }
              public ClassA(int aa)
              {
                  a = aa;
              }
          }
      
          public class ClassB
          {
              private Int32 a;
              private String b;
              private Object c;
      
              public ClassB()
              {
                  a = 123;
                  b = "abc";
                  c = new object();
              }
              public ClassB(int aa)
              {
                  a = aa;
              }
          } 

      編譯成dll后,再用ILSpy查看其IL代碼,發(fā)現(xiàn)ClassA生成的代碼比較多。即每個(gè)構(gòu)造函數(shù)開(kāi)始執(zhí)行處,都會(huì)將字段的默認(rèn)賦值生成IL代碼插入其中。

      ClassA IL代碼如下

      .class public auto ansi beforefieldinit ClassA
      	extends object
      {
      	// Fields
      	.field private int32 a
      	.field private string b
      	.field private object c
      
      	// Methods
      	.method public hidebysig specialname rtspecialname 
      		instance void .ctor () cil managed 
      	{
      		// Method begins at RVA 0x2073
      		// Code size 40 (0x28)
      		.maxstack 8
      
      		IL_0000: ldarg.0
      		IL_0001: ldc.i4.s 123
      		IL_0003: stfld int32 class cnblog_bowen.ClassA::a
      		IL_0008: ldarg.0
      		IL_0009: ldstr "abc"
      		IL_000e: stfld string class cnblog_bowen.ClassA::b
      		IL_0013: ldarg.0
      		IL_0014: newobj instance void object::.ctor()
      		IL_0019: stfld object class cnblog_bowen.ClassA::c
      		IL_001e: ldarg.0
      		IL_001f: call instance void object::.ctor()
      		IL_0024: nop
      		IL_0025: nop
      		IL_0026: nop
      		IL_0027: ret
      	} // End of method ClassA..ctor
      
      	.method public hidebysig specialname rtspecialname 
      		instance void .ctor (
      			int32 aa
      		) cil managed 
      	{
      		// Method begins at RVA 0x209c
      		// Code size 47 (0x2f)
      		.maxstack 8
      
      		IL_0000: ldarg.0
      		IL_0001: ldc.i4.s 123
      		IL_0003: stfld int32 class cnblog_bowen.ClassA::a
      		IL_0008: ldarg.0
      		IL_0009: ldstr "abc"
      		IL_000e: stfld string class cnblog_bowen.ClassA::b
      		IL_0013: ldarg.0
      		IL_0014: newobj instance void object::.ctor()
      		IL_0019: stfld object class cnblog_bowen.ClassA::c
      		IL_001e: ldarg.0
      		IL_001f: call instance void object::.ctor()
      		IL_0024: nop
      		IL_0025: nop
      		IL_0026: ldarg.0
      		IL_0027: ldarg.1
      		IL_0028: stfld int32 class cnblog_bowen.ClassA::a
      		IL_002d: nop
      		IL_002e: ret
      	} // End of method ClassA..ctor
      
      } // End of class cnblog_bowen.ClassA
      

        

      ClassB IL代碼如下

      .class public auto ansi beforefieldinit ClassB
      	extends object
      {
      	// Fields
      	.field private int32 a
      	.field private string b
      	.field private object c
      
      	// Methods
      	.method public hidebysig specialname rtspecialname 
      		instance void .ctor () cil managed 
      	{
      		// Method begins at RVA 0x20cc
      		// Code size 40 (0x28)
      		.maxstack 8
      
      		IL_0000: ldarg.0
      		IL_0001: call instance void object::.ctor()
      		IL_0006: nop
      		IL_0007: nop
      		IL_0008: ldarg.0
      		IL_0009: ldc.i4.s 123
      		IL_000b: stfld int32 class cnblog_bowen.ClassB::a
      		IL_0010: ldarg.0
      		IL_0011: ldstr "abc"
      		IL_0016: stfld string class cnblog_bowen.ClassB::b
      		IL_001b: ldarg.0
      		IL_001c: newobj instance void object::.ctor()
      		IL_0021: stfld object class cnblog_bowen.ClassB::c
      		IL_0026: nop
      		IL_0027: ret
      	} // End of method ClassB..ctor
      
      	.method public hidebysig specialname rtspecialname 
      		instance void .ctor (
      			int32 aa
      		) cil managed 
      	{
      		// Method begins at RVA 0x20f5
      		// Code size 17 (0x11)
      		.maxstack 8
      
      		IL_0000: ldarg.0
      		IL_0001: call instance void object::.ctor()
      		IL_0006: nop
      		IL_0007: nop
      		IL_0008: ldarg.0
      		IL_0009: ldarg.1
      		IL_000a: stfld int32 class cnblog_bowen.ClassB::a
      		IL_000f: nop
      		IL_0010: ret
      	} // End of method ClassB..ctor
      
      } // End of class cnblog_bowen.ClassB
      

      由此看出,雖然默認(rèn)賦值的方法比較直觀和方便,但是從生成的代碼來(lái)看,默認(rèn)賦值的方法會(huì)導(dǎo)致代碼膨脹,所以不應(yīng)在以下場(chǎng)合使用:

      1)字段比較多的Class

      2)構(gòu)造函數(shù)有多個(gè)重載版本

      2. 對(duì)代碼執(zhí)行的影響

      通過(guò)上面的IL代碼,我們發(fā)現(xiàn)默認(rèn)賦值除了會(huì)導(dǎo)致代碼膨脹,賦值的時(shí)機(jī)也和在構(gòu)造函數(shù)中對(duì)字段的賦值不一樣。

      我們知道,類的構(gòu)造函數(shù)在執(zhí)行之前,都會(huì)調(diào)用其基類的構(gòu)造函數(shù),由于所以類都默認(rèn)繼承System.Object,所以上面的ClassA和ClassB雖然沒(méi)有指定基類,

      但都繼承于System.Object,所以都會(huì)調(diào)用System.Object的構(gòu)造函數(shù)。

      調(diào)用System.Object的構(gòu)造函數(shù)的IL代碼即為:call instance void object::.ctor()從上面的IL代碼中,我們發(fā)現(xiàn):

      1)默認(rèn)賦值方式是在調(diào)用System.Object的構(gòu)造函數(shù)前給字段賦值的

      2)構(gòu)造函數(shù)中賦值方式是在調(diào)用System.Object的構(gòu)造函數(shù)后給字段賦值的 這里的差別雖然很小,但是有時(shí)卻會(huì)導(dǎo)致代碼產(chǎn)生不同的結(jié)果,從而帶來(lái)潛在的bug。

      這兩種賦值方式在什么情況下會(huì)導(dǎo)致執(zhí)行結(jié)果不同呢?

      根據(jù)其賦值時(shí)機(jī)的不同,我們可以推斷在如下情況下,兩種賦值方式的執(zhí)行結(jié)果不同。

      基類中調(diào)用虛方法并且如果子類覆蓋(override)了此虛方法,那么此虛方法中的字段就有可能已經(jīng)初始化或者未初始化。

      第一種情況 (默認(rèn)賦值的方式)

          class Test
          {
              static void Main()
              {
                  // 第一步:調(diào)用SubClass的構(gòu)造函數(shù)
                  SubClass sub = new SubClass();
      
                  Console.ReadKey(true);
              }
          }
      
          public class BaseClass
          {
              // 第四步:調(diào)用基類構(gòu)造函數(shù),其中虛方法Print已經(jīng)被子類覆蓋
              public BaseClass()
              {
                  Print();
              }
      
              public virtual void Print()
              {
                  Console.WriteLine("Base class initilized!");
              }
          }
      
          public class SubClass : BaseClass
          {
              // 第三步:對(duì)sub_a,sub_b,obj進(jìn)行賦值,然后再調(diào)用基類構(gòu)造函數(shù)
              private Int32 sub_a = 123;
              private String sub_b = "abc";
              private Object obj = new object();
      
              // 第二步:由于是默認(rèn)賦值的方式,所以先將sub_a,sub_b,obj賦值后再調(diào)用基類構(gòu)造函數(shù)
              public SubClass()
              {
              }
      
              // 第五步:調(diào)用被覆蓋的Print方法,由于obj已被賦值,所以進(jìn)入else分支去執(zhí)行
              public override void Print()
              {
                  if (null == obj)
                      Console.WriteLine("Sub class is uninitilize!");
                  else
                  {
                      Console.WriteLine("a= " + sub_a);
                      Console.WriteLine("b= " + sub_b);
                      Console.WriteLine("Sub class was initilized!");
                  }
              }
          }

      執(zhí)行結(jié)果如下,執(zhí)行過(guò)程可以參見(jiàn)上面代碼中的注釋

      image

      第二種情況(構(gòu)造函數(shù)中對(duì)字段賦值的方式)

          class Test
          {
              static void Main()
              {
                  // 第一步:調(diào)用SubClass的構(gòu)造函數(shù)
                  SubClass sub = new SubClass();
      
                  Console.ReadKey(true);
              }
          }
      
          public class BaseClass
          {
              // 第三步:調(diào)用基類構(gòu)造函數(shù),其中虛方法Print已經(jīng)被子類覆蓋
              public BaseClass()
              {
                  Print();
              }
      
              public virtual void Print()
              {
                  Console.WriteLine("Base class initilized!");
              }
          }
      
          public class SubClass : BaseClass
          {
              private Int32 sub_a;
              private String sub_b;
              private Object obj;
      
              // 第二步:由于是在構(gòu)造函數(shù)對(duì)字段輔助的方式,所以先默認(rèn)調(diào)用基類構(gòu)造函數(shù)
              public SubClass()
              {
                  // 第五步:基類構(gòu)造函數(shù)執(zhí)行完后,進(jìn)入下面的賦值
                  sub_a = 123;
                  sub_b = "abc";
                  obj = new object();
              }
      
              // 第四步:調(diào)用被覆蓋的Print方法,由于obj還未被賦值,所以進(jìn)入if分支去執(zhí)行
              public override void Print()
              {
                  if (null == obj)
                      Console.WriteLine("Sub class is uninitilize!");
                  else
                  {
                      Console.WriteLine("a= " + sub_a);
                      Console.WriteLine("b= " + sub_b);
                      Console.WriteLine("Sub class was initilized!");
                  }
              }
          }

      執(zhí)行結(jié)果如下,執(zhí)行過(guò)程可以參見(jiàn)上面代碼中的注釋

      image

      小小的賦值,也會(huì)導(dǎo)致意外的bug。所以我們?cè)谑褂脮r(shí)默認(rèn)賦值時(shí)一定要對(duì)其賦值的時(shí)機(jī)做到心中有數(shù)。

      posted @ 2011-06-17 16:44  wang_yb  閱讀(1403)  評(píng)論(3)    收藏  舉報(bào)
      主站蜘蛛池模板: 精品国内自产拍在线观看| 亚洲国产五月综合网| 欧美亚洲一区二区三区在线| 国产精品久久毛片| 亚洲色最新高清AV网站| 久久天堂综合亚洲伊人HD妓女| 天天躁夜夜躁av天天爽| 少妇熟女天堂网av| 国产不卡精品视频男人的天堂| 社旗县| 中文字幕无码专区一VA亚洲V专| 日韩精品区一区二区三vr| 国产l精品国产亚洲区| 毛片亚洲AV无码精品国产午夜| 亚洲AV永久无码天堂网一线| 亚洲中文字幕日韩精品| 国产一区视频一区欧美| 777奇米四色成人影视色区| 欧美情侣性视频| 女的被弄到高潮娇喘喷水视频| 久久精品国产再热青青青| 综合偷自拍亚洲乱中文字幕| 亚洲欧美另类久久久精品播放的| 久久久欧美国产精品人妻噜噜| 四虎在线播放亚洲成人| 一本色道久久加勒比综合| 亚洲成a人片在线观看中| 国产成人高清在线观看视频| 四虎在线播放亚洲成人| 成人午夜污一区二区三区| 亚洲春色在线视频| 亚洲精品自拍视频在线看| 精品无码久久久久久久久久| 国产AV大陆精品一区二区三区| 国产精品一二三区蜜臀av| 色九九视频| 无码日韩人妻精品久久| 国产精品一区二区不卡视频| 久久精品国产久精国产一老狼| 亚洲国产成人久久一区久久 | 亚洲an日韩专区在线|