11

最近,我遇到了一个 singelton 类的问题,该类懒惰地初始化一个字典,第二个线程会在它实际被填充之前尝试使用它。所以我通过Lazy<T>类实现了变量初始化。

这是我的代码:

private static Dictionary<string, string> GroupDefaults
{
    get { return mGroupDefaults.Value; }
}
private static Lazy<Dictionary<string, string>> mGroupDefaults =
    new Lazy<Dictionary<string,string>>(delegate
    {
        Dictionary<string, string> defaults = new Dictionary<string, string>();
        foreach (KeyValuePair<string, UnitGroup> groupDef in Groups)
            defaults.Add(groupDef.Key, groupDef.Value.First().Key);
        return defaults;
    });

这解决了问题,现在我正在考虑将此作为我的常规做法,以便Lazy<T>在我进行延迟初始化的任何地方使用该类以避免任何可能的线程问题。所以基本上我想知道这是否是好的/常见的做法?还是会影响性能或其他什么?

4

4 回答 4

12

如果不知道您有什么类型的性能限制,很难说,但根据我的经验,一次性初始化很少是瓶颈(因为根据定义,它只发生一次。)Lazy<T>是为了为您提供这种确切的服务而编写的,所以我会推荐使用它。

于 2012-06-28T01:15:28.360 回答
4

从文档中,我发现以下内容:

如果 Lazy 构造函数中没有传递委托,则在首次访问 value 属性时使用 Activator.CreateInstance 创建包装类型。如果该类型没有默认构造函数,则会引发运行时异常。

Activator.CreateInstance是一种众所周知的不利于性能的方法。但是,在您的情况下,这似乎不是问题,并且无论如何,正如 dlev 所说,调用该方法一次不会成为问题。我没有看到Lazy<T>经常使用它,但我看不出有任何理由在你的情况下不使用它。

于 2012-06-28T01:31:37.863 回答
2

如果这是针对单例的,那么静态构造函数可能就是您想要的。就像是:

class MySingleton
{
    static MySingleton()
    {
         Instance().InitDict();
    }
}
于 2012-06-28T01:27:00.070 回答
1

我认为您可能将 Lazy 用于非预期用途。Lazy 用于某些初始化成本很大的情况,但很可能在对象的生命周期内它可能不会被使用。

如果您总是GroupDefaults在其生命周期中至少调用一次,那么更好的方法是GroupDefaults在容器生命周期开始时在后台线程中进行初始化,并希望在完成初始化之前完成(我知道有一个类,但我需要深入MSDN才能找到)

于 2012-06-28T01:17:21.363 回答