静态构造函数是如何工作的?

namespace MyNameSpace { static class MyClass { static MyClass() { //Authentication process.. User needs to enter password } public static void MyMethod() { //Depends on successful completion of constructor } } class Program { static void Main(string[] args) { MyClass.MyMethod(); } } } 

这是我所设想的顺序

  1. 静态构造函数的开始
  2. 静态构造函数结束
  3. 主要开始
  4. MyMethod的开始
  5. 主要结束

现在在任何情况下,如果4将在2之前开始,我拧。 可能吗?

在这里你只问了一个问题,但是你应该问的问题有十几个,所以我会回答他们。

这是我所设想的顺序

  1. 类的构造函数的开始(也被称为cctor
  2. cctor的结尾
  3. Main的开始
  4. MyMethod的开始

它是否正确?

不正确的顺序是:

  1. 程序的开始,如果有的话。 那没有。
  2. 程序结束,如果有的话。 那没有。
  3. 主要开始
  4. MyClass的cctor的开始
  5. MyClass的cctor结束
  6. MyClass.MyMethod的开始

如果有一个静态字段初始值设定项呢?

在某些情况下,CLR允许更改静态字段初始值设定项的运行顺序。 有关详细信息,请参阅Jon的主题页面。

静态构造函数和types初始值设定项的区别

在类的cctor完成之前是否有可能调用像MyMethod这样的静态方法?

是。 如果cctor本身调用MyMethod,那么明显的MyMethod将在cctor完成之前被调用。

cctor不调用MyMethod。 在MyClass的cctor完成之前是否有可能调用像MyMethod这样的静态方法?

是。 如果cctor使用另一个types的cctor调用MyMethod,那么MyMethod将在MyClass cctor完成之前被调用。

没有cctors直接或间接调用MyMethod! 现在是否有可能在MyClass的cctor完成之前调用像MyMethod这样的静态方法?

没有。

即使涉及多个线程,情况依然如此吗?

是。 在任何线程上可以调用静态方法之前,cctor将在一个线程上完成。

cctor可以被多次调用吗? 假设两个线程都导致cctor运行。

无论涉及多less个线程,cctor保证被最多调用一次。 如果两个线程同时调用MyMethod,则他们竞赛。 其中一人失去了比赛,并阻止直到MyClass cctor完成获胜的线程。

失败的线程阻塞,直到cctor完成? 真的

真。

那么如果获奖线程上的cctor调用阻塞之前由失败线程所使用的锁的代码呢?

那么你有一个经典的locking订单倒置条件。 你的程序死锁。 永远。

这似乎很危险。 我怎样才能避免僵局?

如果这样做会伤害,那么就不要那么做了千万不要做一些可以阻止的事情。

依赖cctor初始化语义来执行复杂的安全性需求是一个好主意吗? 有一个用户交互的cctor是一个好主意吗?

也不是好主意。 我的build议是,您应该find一种不同的方法来确保您的方法的安全影响前提条件得到满足。

根据MSDN ,一个静态构造函数:

在创build第一个实例或引用任何静态成员之前,会自动调用一个静态构造函数来初始化该类。

因此,在调用静态方法MyClass.MyMethod()之前调用静态构造函数(假设在静态构build或静态字段初始化过程中不会调用静态构造函数)。

现在,如果你在static constructor中进行asynchronous操作,那么你的工作就是同步它。

#3实际上是#1:静态初始化直到第一次使用它所属的类才开始。

如果MyMethod是从静态构造函数或静态初始化块中调用的, 如果您不直接或间接从静态构造函数调用MyMethod ,则应该没问题。

从文档 (重点是我的):

创build第一个实例 或引用任何静态成员 之前,会自动调用一个静态构造函数来初始化该类。

你可以保证4总是会在2之后(如果你没有从你的静态方法创build你的类的实例),但是对于1和3也是如此。

静态构造函数将在mymethod执行前被调用。 然而,如果你在2之前调用4,那么我build议你重新考虑你的devise。 无论如何,不​​应该在静态构造函数中做复杂的东西。

CLR保证静态构造函数在任何静态成员被访问之前运行。 但是,你的devise有点臭。 做这样的事情会更直截了当:

 static void Main(string[] args) { bool userIsAuthenticated = MyClass.AuthenticateUser(); if (userIsAuthenticated) MyClass.MyMethod(); } 

使用您的devise,如果身份validation失败,阻止MyMethod运行的唯一方法是抛出exception。

确保静态类的构造函数在其任何方法执行之前被调用。 例:

 class Program { static void Main(string[] args) { Console.WriteLine("Press enter"); Console.ReadLine(); Boop.SayHi(); Boop.SayHi(); Console.ReadLine(); } } static class Boop { static Boop() { Console.WriteLine("Hi incoming ..."); } public static void SayHi() { Console.WriteLine("Hi there!"); } } 

输出:

按回车

//按下后进入

嗨进来…

你好!

你好!

下面是事件发生的顺序:

  1. Main起点
  2. 静态MyClass构造函数的开始
  3. 静态MyClass构造函数结束
  4. MyMethod开始
  5. Main结束

或者你可以在debugging器中完成。