如何在实际需要之前初始化C#静态类?

时间:2012-01-05 19:25:37

标签: c# static

我有一个带静态构造函数的静态类,需要一些时间(10-15秒)来执行并完全初始化类。为了提高性能,我决定启用这个静态类,而不是在第一次需要它时,以便在实际需要使用它时就可以了。

我的第一个想法是为类创建一个Initialize()方法,但是因为我已经有了一个静态构造函数,所以除了作为调用显式初始化的方法之外,这个方法似乎不需要做任何事情。该类没有访问任何其他公共方法或属性。拥有一种不直接做任何事情的方法对我来说似乎不对。

然后我想我可以将代码从静态构造函数移动到这个Initialize()方法中,但是我还希望在首次需要时对类进行初始化并且Initialize()方法不是明确地叫。

总而言之,我希望遵守以下标准:

  • 我想允许显式初始化静态类(可能使用公共Initialize()方法)。
  • 我不想在不需要它时访问该类的任何其他公共方法或属性,即使这会初始化静态类。
  • 如果该类尚未显式初始化,我仍然希望在首次需要时初始化它(即访问其他公共方法或属性时,意图使用它们提供的功能或数据)。
  • 这是一个助手类,我不需要使用Singleton设计模式。

对于用C#编写的静态类,遵循上述标准的正确方法是什么?这也适用于其他编程语言(例如Java),但我个人对使用C#编写的解决方案感兴趣。

5 个答案:

答案 0 :(得分:19)

我会选择初始化方法(编辑:请参阅Jon的回答)。但是,如果你真的只是想使用构造函数,你可以这样做:

var type = typeof (YourType);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);

RunClassConstructor允许您强制类构造函数(静态构造函数)运行(如果它已经没有)。如果它已经运行,比如因为你使用了类的静态成员,那么这没有效果。再运行一次没有效果。

答案 1 :(得分:15)

我可能会选择Initialize方法 - 可以做一些有用的事情:

  • 它可以记录您明确尝​​试使用堆栈跟踪
  • 初始化类
  • 如果通过另一个Initialize调用初始化该类,则可能会抛出异常
  • 您可以可能(通过一些努力和重组)对事物进行排序,以便在初始化期间导致的任何异常都在没有您通常会得到的TypeInitializationException的情况下传播。

答案 2 :(得分:2)

我不确定你是否可以指定何时加载静态构造函数。

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

http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx

* 编辑:* 在这里添加单例模式会有帮助吗? getter可以通过检查类中的标志IsLoaded = true来调用Initialize()。后续调用不会调用Initialize()

答案 3 :(得分:2)

Two work-arounds:

  1. Move the constructor code to Initialize() so you can call explicitly. And replace the code inside the constructor to just call the Initialize() method in case the static class is loaded dynamically before you've called it explicitly

    public static class StaticClass
    {
        // actual constructor
        static StaticClass()
        {
            Initialize();
        }
    
        // explicit "constructor"
        public static void Initialize()
        {
            MyProperty = "Some Value";
        }
    
        public static string MyProperty { get; set; }
    
    }
    

    Then initialize like this if you want:

    StaticClass.Initialize();
    

    Or it will be dynamically initialized the first time it's used

  2. Not as semantically pristine, but you can trigger the organic initialization of a static class just by consuming a property and throwing it in a temporary variable.

    So just do this:

    // trigger static initilaization
    var dummy = StaticClass.MyProperty;
    

    Still allows you to call it whenever you need to, but if there is some performance cost on initialization, you can try to invoke it on startup, rather than the first time the user does something that fires that code.

For another helpful outline of static initialization see: Is the order of static class initialization in C# deterministic?

答案 4 :(得分:0)

这种做法对我来说似乎并不惹人注意。我可能将方法命名为Touch(),给它一个空体,并添加适当的注释。这足以让你感觉到某些事情对此感觉不正确吗?