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

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

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

      為什么應(yīng)該盡可能避免在靜態(tài)構(gòu)造函數(shù)中初始化靜態(tài)字段?

      C#具有一個(gè)默認(rèn)開啟的代碼分析規(guī)則:[CA1810]Initialize reference type static fields inline,推薦我們以內(nèi)聯(lián)的方式初始化靜態(tài)字段,而不是將初始化放在靜態(tài)構(gòu)造函數(shù)中。

      一、兩種初始化的性能差異
      二、beforefieldinit標(biāo)記
      三、靜態(tài)構(gòu)造函數(shù)執(zhí)行的時(shí)機(jī)
      四、關(guān)于“All-Zero”結(jié)構(gòu)體
      五、RuntimeHelpers.RunClassConstructor方法

      一、兩種初始化的性能差異

      CA1810這一規(guī)則與性能有關(guān),我們可以利用如下這段簡(jiǎn)單的代碼來演示兩種初始化的性能差異。Foo和Bar這兩個(gè)類的靜態(tài)字段都定義了一個(gè)名為_value的靜態(tài)字段,它們均通過調(diào)用靜態(tài)方法Initialize返回的值進(jìn)行初始化。不同的是Foo以內(nèi)聯(lián)(inline)賦值的方法進(jìn)行初始化,而Bar則將初始化操作定義在靜態(tài)構(gòu)造函數(shù)中。假設(shè)Initialize方法是一個(gè)相對(duì)耗時(shí)的操作,我們利用Program的_initialized字段判斷該方法是否被調(diào)用。

      static class Program
      {
          private static bool _initialized;
          static void Main()
          {
              Foo.Invoke();
              Debug.Assert(_initialized == false);
      
              Bar.Invoke();
              Debug.Assert(_initialized == true);
          }
          private static int Initialize()
          {
              _initialized = true;
              return 123;
          }
          public class Foo
          {
              private readonly static int _value = Initialize();
              public static int Value => _value;
              public static void Invoke() { }
          }
          public class Bar
          {
              private readonly static int _value;
              public static int Value => _value;
              static Bar() => _value = Initialize();
              public static void Invoke() { }
          }
      }

      從我們給出的調(diào)用斷言可以確定,當(dāng)我們調(diào)用Foo的靜態(tài)方法Invoke時(shí),它的靜態(tài)字段_value并沒有初始化;但是當(dāng)我們調(diào)用Bar的Invoke方法時(shí),Initialize方法會(huì)率先被調(diào)用來初始化靜態(tài)字段。從這個(gè)例子來說,由于整個(gè)應(yīng)用并沒有使用到Foo和Bar的靜態(tài)字段,所以針對(duì)它們的初始化是沒有必要的。所以我們說以內(nèi)聯(lián)方式對(duì)靜態(tài)字段進(jìn)行初始化的Foo具有更好的性能。

      二、beforefieldinit標(biāo)記

      對(duì)于Foo和Bar這兩個(gè)類型表現(xiàn)出來的不同行為,我們可以試著從IL代碼層面尋找答案。如下所示的兩段IL代碼分別來源于Foo和Bar,我們可以看到雖然Foo類中沒有顯式定義靜態(tài)構(gòu)造函數(shù),但是編譯器會(huì)創(chuàng)建一個(gè)默認(rèn)的靜態(tài)構(gòu)造函數(shù),針對(duì)靜態(tài)字段的初始化就放在這里。我們可以進(jìn)一步看出,自動(dòng)生成的這個(gè)靜態(tài)構(gòu)造函數(shù)和我們自己寫的并沒有本質(zhì)的不同。兩個(gè)類型之間的差異并沒有體現(xiàn)在靜態(tài)構(gòu)造函數(shù)上,而是在于:沒有顯式定義靜態(tài)構(gòu)造函數(shù)的Foo類型上具有一個(gè)beforefieldinit標(biāo)記。

      .class public auto ansi beforefieldinit Foo extends [System.Runtime]System.Object { .field private static initonly int32 _value .method private hidebysig specialname rtspecialname static void .cctor () cil managed { .maxstack 8 IL_0000: call int32 Program::Initialize() IL_0005: stsfld int32 Foo::_value IL_000a: ret }

      … }

      .class public auto ansi Bar
      	extends [System.Runtime]System.Object
      {
      
      	.field private static initonly int32 _value	
      	.method private hidebysig specialname rtspecialname static
      		void .cctor () cil managed
      	{
      		.maxstack 8
      
      		IL_0000: call int32 Program::Initialize()
      		IL_0005: stsfld int32 Bar::_value
      		IL_000a: ret
      	} 
      	
      } 
      

      三、靜態(tài)構(gòu)造函數(shù)執(zhí)行的時(shí)機(jī)

      從Foo和Bar的IL代碼可以看出,針對(duì)它們靜態(tài)字段的初始化都放在靜態(tài)構(gòu)造函數(shù)中。但是當(dāng)我們調(diào)用一個(gè)并不涉及類型靜態(tài)字段的Invoke方法時(shí),定義在Foo中的靜態(tài)構(gòu)造函數(shù)會(huì)自動(dòng)執(zhí)行,但是定義在Bar中的則不會(huì),由此可以看出一個(gè)類型的靜態(tài)構(gòu)造函數(shù)的執(zhí)行時(shí)機(jī)與類型是否具有beforefieldinit標(biāo)記有關(guān)。具體規(guī)則如下,這一個(gè)規(guī)則直接定義在CLI標(biāo)準(zhǔn)ECMA-335中,靜態(tài)構(gòu)造函數(shù)在此標(biāo)準(zhǔn)中被稱為類型初始化器(Type Initializer)或者.cctor。

      • 具有beforefieldinit標(biāo)記:靜態(tài)構(gòu)造函數(shù)會(huì)在第一次讀取任何一個(gè)靜態(tài)字段之前自動(dòng)執(zhí)行,這相當(dāng)于一種Lazy loading的模式;
      • 不具有beforefieldinit標(biāo)記:靜態(tài)構(gòu)造函數(shù)會(huì)在如下場(chǎng)景下自動(dòng)執(zhí)行:
        • 第一次讀取任何一個(gè)靜態(tài)字段之前;
        • 第一個(gè)執(zhí)行任何一個(gè)靜態(tài)方法之前;
        • 引用類型:第一次調(diào)用構(gòu)造函數(shù)之前;
        • 值類型:第一次調(diào)用實(shí)例方法;

      由于beforefieldinit標(biāo)記只有在沒有顯式定義靜態(tài)構(gòu)造函數(shù)的情況下才會(huì)被添加,所以我們自行定義的專門用來初始化靜態(tài)字段的靜態(tài)構(gòu)造函數(shù)是完全沒有必要的。不但沒有必要,還可能帶來性能問題,應(yīng)該改成以內(nèi)聯(lián)的形式對(duì)靜態(tài)字段進(jìn)行初始化。

      四、關(guān)于“All-Zero”結(jié)構(gòu)體

      如果我們?cè)谝粋€(gè)結(jié)構(gòu)體中顯式定義了一個(gè)靜態(tài)構(gòu)造函數(shù),當(dāng)我們調(diào)用其構(gòu)造函數(shù)之前,靜態(tài)構(gòu)造函數(shù)會(huì)自動(dòng)執(zhí)行。

      public class Program
      {
          private static bool _initialized= false;
      
          static void Main()
          {
              var foobar = new Foobar(1, 2);
              Debug.Assert(_initialized == true);
          }
      
          public struct Foobar
          {
              static Foobar() => _initialized = true;
              public Foobar(int foo, int bar)
              {
                  Foo = foo;
                  Bar = bar;
              }
      
              public int Foo { get; }
              public int Bar { get; }
          }
      }

      倘若按照如下的方式利用default關(guān)鍵字得到一個(gè)所有字段為“零”的默認(rèn)結(jié)構(gòu)體(all-zero structure),我們顯式定義的靜態(tài)構(gòu)造函數(shù)是不會(huì)執(zhí)行的。

      public class Program
      {
          private static bool _initialized = false;
      
          static void Main()
          {
              Foobar foobar = default;
              Debug.Assert(foobar.Foo == 0);
              Debug.Assert(foobar.Bar == 0);
              Debug.Assert(_initialized == false);
          }
          ...
      }

      五、RuntimeHelpers.RunClassConstructor方法

      如果我們要確保某個(gè)類型的靜態(tài)構(gòu)造函數(shù)已經(jīng)被顯式調(diào)用,可以執(zhí)行RuntimeHelpers.RunClassConstructor方法,它的參數(shù)為目標(biāo)類型的TypeHandle。

      public class Program { private static bool _initialized = false; static void Main() { RuntimeHelpers.RunClassConstructor(typeof(Foobar).TypeHandle); Debug.Assert(_initialized == true); }

      … }

      由于類型的靜態(tài)構(gòu)造函數(shù)只會(huì)被執(zhí)行一次,所以多次RuntimeHelpers.RunClassConstructor并不會(huì)導(dǎo)致靜態(tài)函數(shù)的重復(fù)執(zhí)行。

      public class Program { private static bool _initialized = false; static void Main() { RuntimeHelpers.RunClassConstructor(typeof(Foobar).TypeHandle); Debug.Assert(_initialized == true); _typeInitializerInvoked = false;
      RuntimeHelpers.RunClassConstructor(typeof(Foobar).TypeHandle); Debug.Assert(_initialized == false); } ... }

      posted @ 2023-07-10 08:36  Artech  閱讀(2936)  評(píng)論(6)    收藏  舉報(bào)
      主站蜘蛛池模板: 亚洲天堂一区二区三区四区| 库尔勒市| 国产乱码精品一区二区上| 日日爽日日操| 欧洲亚洲国内老熟女超碰| 亚洲欧美日韩成人综合一区 | 麻豆蜜桃伦理一区二区三区| 老色鬼在线精品视频| 国产97人人超碰caoprom| 国产第一页浮力影院入口| 亚洲韩国精品无码一区二区三区| 99久久精品午夜一区二区| 四虎精品国产永久在线观看| 天天摸天天做天天爽水多| 中文字幕精品亚洲字幕成| 熟女激情乱亚洲国产一区| 亚洲精品爆乳一区二区H| 精品亚洲女同一区二区| 丝袜无码一区二区三区| 成人国产av精品免费网| 亚洲国产精品一区二区久| 老司机免费的精品视频| 国产在线精品欧美日韩电影 | 日本久久99成人网站| 玛多县| 国产台湾黄色av一区二区| 中文字幕国产精品自拍| 欧美日本在线一区二区三区| 97成人碰碰久久人人超级碰oo| 久久精品免费自拍视频| 成人免费AA片在线观看| 独山县| 久久蜜臀av一区三区| 精品中文人妻中文字幕| 色综合热无码热国产| 青青草国产精品日韩欧美| 国内自拍小视频在线看| 亚洲精品成人7777在线观看 | 国内精品久久久久影院日本| 欧美不卡无线在线一二三区观| 色老头在线一区二区三区|