如何在实际需要之前初始化 C# 静态类
本文关键字:初始化 静态类 实际需要 | 更新日期: 2023-09-27 18:19:29
我有一个带有静态构造函数的静态类,需要一些时间(10-15 秒(来执行和完全初始化该类。为了提高性能,我决定允许显式初始化这个静态类,而不是在第一次需要它的时候,以便在实际需要使用它时准备好使用它。
我的第一个想法是为类创建一个 Initialize()
方法,但由于我已经有一个静态构造函数,因此此方法似乎不需要执行任何其他操作,只需调用该方法以显式初始化类而不访问其任何其他公共方法或属性。对我来说,拥有一种不直接执行任何操作的方法似乎不对。
然后我想我可以将代码从静态构造函数移动到这个 Initialize()
方法中,但我也希望在第一次需要时初始化该类并且未显式调用 Initialize()
方法。
总而言之,我希望遵守以下标准:
- 我想允许显式初始化静态类(可能通过使用公共
Initialize()
方法(。 - 当我不需要它们时,我不想访问类上的任何其他公共方法或属性,即使这会初始化静态类。
- 如果类尚未显式初始化,我仍然希望在第一次需要时初始化它(即在访问其他公共方法或属性以使用它们提供的功能或数据时(。
- 这是一个帮助程序类,对于我的目的来说,使用单例设计模式不是必需的。
对于用 C# 编写的静态类,遵守上述标准的正确方法是什么?这也适用于其他编程语言(例如Java(,但我个人对用C#编写的解决方案感兴趣。
我会使用初始化方法(编辑:参见Jon的答案(。但是如果你真的只想使用构造函数,你可以这样做:
var type = typeof (YourType);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
RunClassConstructor
允许您强制类构造函数(静态构造函数(运行(如果它还没有(。如果它已经运行,比如因为你使用了类的静态成员,那么这不起作用。再运行几次不起作用。
我可能会选择Initialize
的方法 - 它可以做一些有用的事情:
- 它可以记录您正在使用堆栈跟踪显式尝试初始化类
- 如果类已通过另一个
Initialize
调用初始化,则可能会引发异常 -
您可以(通过一些努力和重组(对事物进行排序,以便在初始化期间引起的任何异常在没有通常获得
TypeInitializationException
的情况下传播。
只需调用类上的任何成员将强制构造函数运行,因此您可以获取现有属性,例如:
// trigger static initialization
var _ = StaticClass.MyProperty;
为了使代码更加自我记录,您可以添加一个空的、无参数的、void 的方法,称为类似于 Initialize
的方法,以便代码以更多的意图读取。
public static class StaticClass
{
static StaticClass()
{
// any logic you want in the constructor
}
/// <summary> Blank Method which will force constructor of static class </summary>
public static void Initialize() { }
}
然后,您可以在启动期间调用,如下所示:
StaticClass.Initialize();
.NET 小提琴中的演示
另请参阅:C# 中静态类初始化的顺序是否具有确定性?
更新:我之前曾建议将启动逻辑放在 Initialize 方法中,并从 ctor 调用,但是,正如 Smart Humanism 指出的那样,这将导致Initialize
被调用两次的竞争条件
我不确定是否可以指定何时加载静态构造函数。
来自 MSDN"在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数以初始化类。">
http://msdn.microsoft.com/en-US/library/K9x6W0HC(v=vs.80(.aspx
*编辑: *在这里添加单例模式会有所帮助吗?getter 可以通过检查类中的标志 IsLoaded=true 来调用 Initialize((。后续调用将不会调用 Initialize((
似乎并不令人讨厌。我可能会将该方法命名为 Touch((,给它一个空的主体,并添加适当的注释。这是否足以让你克服你觉得有些不对劲的感觉?