How does a static constructor work?

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();
}
}
}

Here is the sequence which I assumed

  1. Start of static constructor
  2. End of static constructor
  3. Start of main
  4. Start of MyMethod
  5. End of main

Now in any scenario if 4 will start before 2 I am screwed. Is it possible?

11236 次浏览

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

如果从静态构造函数或静态初始化块调用 MyMethod,那么这是可能的。如果不从静态构造函数直接或间接调用 MyMethod,应该没有问题。

根据 MSDN,静态构造函数:

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

因此,在调用静态方法 MyClass.MyMethod()之前,将调用静态构造函数(当然,前提是在静态构造或静态字段初始化期间没有调用 还有)。

现在,如果您在 static constructor中执行任何异步操作,那么您的工作就是同步它。

来自 文件(强调地雷) :

将自动调用静态构造函数来初始化该类 在创建第一个实例 或任何静态成员之前 参考资料 .

你可以保证4总是在2之后(如果你没有从静态方法中创建类的实例的话) ,但是对于1和3来说并不是这样。

在执行 mymethod 之前将调用静态构造函数。然而,如果你是螺丝,如果4被称为前2然后我建议你重新考虑你的设计。无论如何都不应该在静态构造函数中做复杂的事情。

CLR 保证静态构造函数在访问任何静态成员之前运行。但是,你的设计有点臭。这样做会更直接:

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

在您的设计中,如果身份验证失败,阻止 MyMethod 运行的唯一方法是引发异常。

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

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. 类构造函数的开始(也称为 cctor)
  2. 到此为止
  3. 主干道起点
  4. 开始使用 MyMethod

是这样吗?

不,正确的顺序是:

  1. 开始 cctor 的程序,如果有的话。没有。
  2. 程序的 cctor 结束,如果有的话。没有。
  3. 主干道起点
  4. MyClass 的 cctor 启动
  5. MyClass 的 cctor 结束
  6. 开始 MyClass.MyMethod

如果有一个静态字段初始化程序会怎样?

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

静态构造函数和类型初始值设定项之间的区别

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

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

Cctor 不调用 MyMethod。有没有可能在 MyClass 的 ctor 完成之前调用像 MyMethod这样的静态方法?

是的,如果 cctor 使用其 cctor 调用 MyMethod 的另一种类型,那么 MyMethod 将在 MyClass cctor 完成之前被调用。

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

没有。

即使涉及到多个线程,这是否仍然成立?

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

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

不管涉及多少个线程,cctor 最多只能被调用一次。如果两个线程“同时”调用 MyMethod,那么它们就会竞争。其中一个输掉了比赛并且阻止,直到 MyClass ctor 在获胜线程上完成。

在 cctor 完成之前丢失的线程 积木? 真的

真的。

那么,如果 胜利线程上的 cctor 调用阻塞 输了线程以前获取的锁的代码,会怎么样呢?

然后你有一个经典的锁定顺序反转条件。你的程序死锁。永远。

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

如果这样做会痛,那么 别这样.永远不要做一些可以阻塞 ctor 的事情。

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

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

或者可以在调试器中单步执行。

下面是事情发生的实际顺序:

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