C# 中靜態建構函式有什麼用?


靜態建構函式用於初始化任何靜態資料,或執行只需要執行一次的特定操作。在建立第一個例項或引用任何靜態成員之前,它會自動呼叫。

在為非託管程式碼建立包裝類時,靜態建構函式很有用,因為建構函式可以呼叫 LoadLibrary 方法。靜態建構函式也是一個方便的地方,用於對型別引數執行執行時檢查,而這些檢查無法透過約束在編譯時進行檢查。

靜態建構函式具有以下屬性:

  • 靜態建構函式不接受訪問修飾符或引數。

  • 一個類或結構只能有一個靜態建構函式。

  • 靜態建構函式不能被繼承或過載。

  • 靜態建構函式不能直接呼叫,僅供公共語言執行時 (CLR) 呼叫。它是自動呼叫的。

  • 使用者無法控制靜態建構函式在程式中何時執行。

  • 靜態建構函式在建立第一個例項或引用任何靜態成員之前自動呼叫以初始化類。靜態建構函式將在例項建構函式之前執行。當分配給事件或委託的靜態方法被呼叫時,會呼叫型別的靜態建構函式,而不是在分配時呼叫。如果靜態欄位變數初始化程式存在於靜態建構函式的類中,則它們將在類宣告中出現的文字順序中立即在靜態建構函式執行之前執行。

  • 如果您不提供靜態建構函式來初始化靜態欄位,則所有靜態欄位都將初始化為其預設值,如 C# 型別預設值中所列。

  • 如果靜態建構函式引發異常,則執行時將不會第二次呼叫它,並且該型別將在程式執行的應用程式域的整個生命週期內保持未初始化狀態。最常見的是,當靜態建構函式無法例項化型別或靜態建構函式中發生的未處理異常時,會引發 TypeInitializationException 異常。對於在原始碼中未顯式定義的隱式靜態建構函式,故障排除可能需要檢查中間語言 (IL) 程式碼。

  • 靜態建構函式的存在會阻止新增 BeforeFieldInit 型別屬性。這限制了執行時最佳化。

  • 宣告為 static readonly 的欄位只能在其宣告中或在靜態建構函式中分配。當不需要顯式靜態建構函式時,請在宣告中初始化靜態欄位,而不是透過靜態建構函式進行初始化,以獲得更好的執行時最佳化。

示例

 線上演示

using System;
namespace DemoApplication{
   public class Program{
      static void Main(string[] args){
         Car user = new Car();
         Car user1 = new Car();
         Console.ReadLine();
      }
   }
   public class Car{
      static Car(){
         Console.WriteLine("Static constructor called");
      }
      public Car(){
         Console.WriteLine("Default constructor called");
      }
   }
}

輸出

Static constructor called
Default constructor called
Default constructor called

在上面的示例中,我們可以看到靜態建構函式僅呼叫一次。

示例

 線上演示

using System;
using System.Threading;
namespace DemoApplication{
   public class Car{
      protected static readonly DateTime globalStartTime;
      protected int RouteNumber { get; set; }
      static Car(){
         globalStartTime = DateTime.Now;
         Console.WriteLine($"Static constructor called. Global start time:
         {globalStartTime.ToLongTimeString()}");
      }
      public Car(int routeNum){
         RouteNumber = routeNum;
         Console.WriteLine($"Car {RouteNumber} is created.");
      }
      public void Drive(){
         TimeSpan elapsedTime = DateTime.Now - globalStartTime;
         Console.WriteLine($"Car {this.RouteNumber} is starting its route
         {elapsedTime.Milliseconds} minutes after global start time
         {globalStartTime.ToShortTimeString()}.");
      }
   }
   class TestCar{
      static void Main(){
         Car car1 = new Car(1);
         Car car2 = new Car(2);
         car1.Drive();
         Thread.Sleep(25);
         car2.Drive();
         Console.ReadLine();
      }
   }
}

輸出

Static constructor called. Global start time:
7:09:06 AM
Car 1 is created.
Car 2 is created.
Car 1 is starting its route25 minutes after global start time7:09 AM.
Car 2 is starting its route50 minutes after global start time7:09 AM.

更新於:2020 年 9 月 24 日

3K+ 次檢視

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.