静态构造函数是如何工作的?
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(); } } }
这是我所设想的顺序
- 静态构造函数的开始
- 静态构造函数结束
- 主要开始
- MyMethod的开始
- 主要结束
现在在任何情况下,如果4将在2之前开始,我拧。 可能吗?
在这里你只问了一个问题,但是你应该问的问题有十几个,所以我会回答他们。
这是我所设想的顺序
- 类的构造函数的开始(也被称为
cctor
) - cctor的结尾
- Main的开始
- MyMethod的开始
它是否正确?
不正确的顺序是:
- 程序的开始,如果有的话。 那没有。
- 程序结束,如果有的话。 那没有。
- 主要开始
- MyClass的cctor的开始
- MyClass的cctor结束
- 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!"); } }
输出:
按回车
//按下后进入
嗨进来…
你好!
你好!
下面是事件发生的顺序:
-
Main
起点 - 静态
MyClass
构造函数的开始 - 静态
MyClass
构造函数结束 -
MyMethod
开始 -
Main
结束
或者你可以在debugging器中完成。