歡迎您光臨本站 註冊首頁

c# 類成員初始化順序的特殊情況

←手機掃碼閱讀     kyec555 @ 2020-07-01 , reply:0

這裡直接給出C#類成員一般初始化順序:

  1. 子類靜態字段

  2. 子類靜態構造

  3. 子類實例字段

  4. 父類靜態字段

  5. 父類靜態構造

  6. 父類實例字段

  7. 父類實例構造

  8. 子類實例構造

為什麼說是“一般”初始化順序呢?因為根據類結構的不同,類成員的初始化順序並不是一成不變的。但是這個順序是基礎,可以推導出其他特殊的初始化順序。下面我們就來看兩種特殊的情況:

  static void Main(string[] args)  {    Console.WriteLine("---------------一般初始化順序---------------");    var child1 = new Child1();    Console.WriteLine(" ---------------子類靜態字段初始化需要使用父類靜態字段時初始化順序---------------");    var child2 = new Child2();    Console.WriteLine(" ---------------子類靜態構造函數中使用父類靜態字段時初始化順序---------------");    var child3 = new Child3();      Console.ReadKey();  }    public class Child1 : Base1  {    public static Display ChildStatic = new Display("Child static filed");      private Display _childFiled = new Display("Child filed");      static Child1() => Console.WriteLine("Child static ctor");      public Child1() => Console.WriteLine("Child ctor");  }    public class Child2 : Base2  {    ////// 子類靜態字段初始化需要使用父類靜態字段    ///public static Display ChildStatic = new Display("Child static filed", () => BaseStatic);      private Display _childFiled = new Display("Child filed");      static Child2() => Console.WriteLine("Child static ctor");      public Child2() => Console.WriteLine("Child ctor");  }    public class Child3 : Base3  {    public static Display ChildStatic = new Display("Child static filed");      private Display _childFiled = new Display("Child filed");      ////// 子類靜態構造函數中使用父類靜態字段    ///static Child3()    {      Console.WriteLine("Child static ctor");      var baseStatic = BaseStatic;    }      public Child3() => Console.WriteLine("Child ctor");  }    ////// 3個Base類相同,這裡是為了演示靜態成員的初始化  ///public class Base1  {    public static Display BaseStatic = new Display("Base static filed");      private Display _baseFiled = new Display("Base filed");      static Base1() => Console.WriteLine("Base static ctor");      public Base1() => Console.WriteLine("Base ctor");  }    public class Base2  {    public static Display BaseStatic = new Display("Base static filed");      private Display _baseFiled = new Display("Base filed");      static Base2() => Console.WriteLine("Base static ctor");      public Base2() => Console.WriteLine("Base ctor");  }    public class Base3  {    public static Display BaseStatic = new Display("Base static filed");      private Display _baseFiled = new Display("Base filed");      static Base3() => Console.WriteLine("Base static ctor");      public Base3() => Console.WriteLine("Base ctor");  }    public class Display  {    public Display(string msg, FuncdisplayFunc = null)    {      Console.WriteLine(msg);      var display = displayFunc?.Invoke();    }  }

 

補充一下:

1. 靜態構造函數是線程安全的,會在初次訪問該類所定義的其他方法、屬性或變量之前執行

2. 編譯器會在每個構造函數(包括靜態和實例)的開頭放入適當的程序碼,以便把你在定義成員字段時所指定的初始值設置給這些變量,這就是字段總是在構造函數執行前初始化的原因。

3. 無論是靜態變量還是實例變量,其取值都應該在聲明的時候得以初始化。但以下3種情況不應該編寫初始化語句

  • 把字段初始化為0或null。因為系統在執行開發者編寫的代碼之前,就會把內存清零,重複執行清零指令就顯得多餘了

  • 字段的初始值需要根據不同的構造函數來設定。這種情況下字段的初始化放在構造函數中就可以了,否則會導致創建多餘的對象

  • 字段的初始化過程中可能出現異常。這種也應該放在構造函數中進行初始化,同時要注意千萬不能讓靜態構造函數中的異常脫出,因為一個AppDomain僅能調用一次某個類的靜態構造函數

通過了解類成員的初始化順序,可以讓我們更加詳細地瞭解程序執行的細節,避免寫出類似“在構造函數中調用虛函數或抽象函數”的代碼。


[kyec555 ] c# 類成員初始化順序的特殊情況已經有1110次圍觀

http://coctec.com/docs/c/language/show-post-240525.html