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

在上面的示例中,我们可以看到静态构造函数仅调用一次。

Learn C# in-depth with real-world projects through our C# certification course. Enroll and become a certified expert to boost your career.

示例

 在线演示

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+ 次查看

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告