C# 存在lock语句时,字段初始化在静态类中不起作用,这是一个奇怪的问题

C# 存在lock语句时,字段初始化在静态类中不起作用,这是一个奇怪的问题,c#,locking,C#,Locking,我在asp.net mvc应用程序中使用了以下静态类(为了清晰起见,进行了简化) public static class GObjContextHelper { private static readonly object _lock = new object(); public static GObjContext GetObjContext() { Trace.TraceInformation("_lock: " + _lock); //lock (_lock

我在asp.net mvc应用程序中使用了以下静态类(为了清晰起见,进行了简化)

public static class GObjContextHelper
{
  private static readonly object _lock = new object();

  public static GObjContext GetObjContext()
  {
    Trace.TraceInformation("_lock: " + _lock);

    //lock (_lock)
    //{
    //Trace.TraceInformation("exclusive section");
    //}
    return null;
  }
  ....
}
除非未注释锁块,否则它工作得非常好。 此时_lock字段停止初始化-_lock为空,可通过调试器或跟踪信息进行验证。 事实上,一旦存在锁块,任何字段的内联和使用静态构造函数的初始化都会停止工作。 更奇怪的是,这只发生在这个特殊的类中。我无法在应用程序中的任何其他静态类中复制它

我有一种感觉,我错过了一些令人尴尬的琐事

[编辑]

事实证明(我应该首先提供一个更完整的示例。)其中一个字段变量在内部引用了GObjContextHelper.GetObjContext()。修复此循环引用后,一切正常

我仍然希望解释一下静态类初始化过程中会发生什么,其中字段变量是在构造函数中引用上述静态类的对象。以及为什么lock语句对变量的初始化顺序有这样的影响

一个更详细的例子:

public static class GObjContextHelper
{
    private static TestService testService = new TestService();
    private static readonly object _lock = new object();

    public static GObjContext GetObjContext()
    {
        Trace.TraceInformation("_lock: " + _lock);         

        // _lock is properly initialized if this lock block is commented out.
        // otherwise _lock is null
        //lock (_lock)
        //{
        //}
        return null;
      }
    public static object Account { get { return testService.GetCurrentAccount(); } }
}


public class TestService
{
    GObjContext context;

    public AccountService()
    {
        context = GObjContextHelper.GetObjContext();
    }

    public object GetCurrentAccount()
    {
        return null;
    }
}

您完全可以通过以下方式停止担心:

public static class GObjContextHelper
{
  private static object _lock;

  public static GObjContext GetObjContext()
  {
    Trace.TraceInformation("_lock: " + _lock);

    lock (GetLockObject())
    {
      Trace.TraceInformation("exclusive section");
    }
    return null;
  }

  private static object GetLockObject()
  {
    if (_lock == null)
    {
      _lock = new object();
    }

    return _lock;
  }
  ....
}

您完全可以通过以下方式停止担心:

public static class GObjContextHelper
{
  private static object _lock;

  public static GObjContext GetObjContext()
  {
    Trace.TraceInformation("_lock: " + _lock);

    lock (GetLockObject())
    {
      Trace.TraceInformation("exclusive section");
    }
    return null;
  }

  private static object GetLockObject()
  {
    if (_lock == null)
    {
      _lock = new object();
    }

    return _lock;
  }
  ....
}

如果要对静态字段进行确定性初始化,则需要使用静态构造函数:

public static class GObjContextHelper
{
  private static readonly object _lock;
  static GObjContextHelper() 
  {
    _lock = new object();
  }
}
您还可以通过指定静态构造函数来强制字段初始化。这会告诉c#编译器,您的类型不会被标记为beforefieldinit CIL属性

public static class GObjContextHelper
{
  private static readonly object _lock = new object();
  static GObjContextHelper() 
  {
  }
}

如果要对静态字段进行确定性初始化,则需要使用静态构造函数:

public static class GObjContextHelper
{
  private static readonly object _lock;
  static GObjContextHelper() 
  {
    _lock = new object();
  }
}
您还可以通过指定静态构造函数来强制字段初始化。这会告诉c#编译器,您的类型不会被标记为beforefieldinit CIL属性

public static class GObjContextHelper
{
  private static readonly object _lock = new object();
  static GObjContextHelper() 
  {
  }
}

我认为C#中的静态字段初始化顺序是不确定的,所以这可能是问题所在。我不知道。这个独立的代码片段在VS2010中对我很有用。您何时/何处调用GetObjContext?从另一个静态场?例如,私有静态GObjContext=GetObjContext()
GObjContextHelper
是分部类吗?另一个源文件中的静态字段初始值设定项是否使用了
GetObjContext
方法?我已经更新了这个问题。很抱歉之前没有提供更详细的示例。我认为C#中的静态字段初始化顺序是不确定的,所以这可能就是问题所在。我不知道。这个独立的代码片段在VS2010中对我很有用。您何时/何处调用GetObjContext?从另一个静态场?例如,私有静态GObjContext=GetObjContext()
GObjContextHelper
是分部类吗?另一个源文件中的静态字段初始值设定项是否使用了
GetObjContext
方法?我已经更新了这个问题。抱歉,之前没有提供更详细的示例。您的示例中有一个输入错误,您应该锁定返回的对象,而不是方法groupI更新了问题。抱歉,之前没有提供更详细的示例。您的示例中有一个输入错误,您应该锁定返回的对象,而不是方法groupI更新了问题。很抱歉之前没有提供更详细的示例。我已经更新了问题。很抱歉之前没有提供更详细的示例。我已经更新了问题。很抱歉,之前没有提供更详细的示例。