一个只读静态字段如何为空?

时间:2010-01-11 17:12:42

标签: c# asp.net-mvc static readonly nullreferenceexception

所以这是我的一个课程的摘录:

    [ThreadStatic]
    readonly static private AccountManager _instance = new AccountManager();

    private AccountManager()
    {
    }

    static public AccountManager Instance
    {
        get { return _instance; }
    }

如您所见,它是每个线程的单例 - 即该实例标有ThreadStatic属性。该实例也被实例化为静态构造的一部分。

既然如此,当我尝试使用Instance属性时,我的ASP.NET MVC应用程序中是否有可能出现NullReferenceException?

5 个答案:

答案 0 :(得分:38)

引用MSDN ThreadStaticAttribute

  

不要指定初始值   标有的字段   ThreadStaticAttribute,因为这样   初始化只发生一次,何时   类构造函数执行,和   因此只影响一个线程。如果   你没有指定初始值,   你可以依靠现场   如果它初始化为其默认值   是值类型,还是null   引用(在Visual Basic中没有任何内容)if   它是一种参考类型。

答案 1 :(得分:12)

这是ThreadStatic属性的一个令人困惑的部分。即使它为每个线程创建一个值,初始化代码也只在其中一个线程上运行。访问此值的所有其他线程将获得该类型的默认值,而不是初始化代码的结果。

而不是值初始化,将其包装在为您进行初始化的属性中。

[ThreadStatic]
readonly static private AccountManager _instance;

private AccountManager()
{
}

static public AccountManager Instance
{
  get 
  { 
    if ( _instance == null ) _instance = new AccountManager();
    return _instance; 
  }
}

因为每个线程的值_instance是唯一的,所以在属性中不需要锁定,并且可以将其视为任何其他延迟初始化值。

答案 2 :(得分:8)

你在这里击中了经典的[ThreadStatic]“101”。

静态初始化程序只会触发一次,即使它被标记为[ThreadStatic],所以其他线程(除了第一个)都会看到这个未初始化。

答案 3 :(得分:1)

我相信正在发生的事情是静态字段只被初始化一次,所以当另一个线程尝试读取字段时它将为null(因为它是默认值),因为_instance不能再次初始化。它只是一个想法,但我可以完全离开,但这就是我认为正在发生的事情。

答案 4 :(得分:0)

线程之间不共享标有ThreadStaticAttribute的静态字段。每个执行线程都有一个单独的字段实例,并独立设置和获取该字段的值。如果在另一个线程上访问该字段,它将包含不同的值。