使用 new 的静态变量初始化会产生代码危险



我正在处理一些代码,如下所示:

class A
{
   static SomeClass a = new Someclass("asfae");  
}

某个类包含所需的构造函数。此代码编译良好,没有任何警告。但是我在系统中遇到了代码危险:

"Someclass ctor 已从静态构造函数和/或调用 静态初始化器"

此代码危害系统的一部分只是通过警告系统中可能存在的缺陷或系统可能因此而进入错误状态来使其更好。我在网络上的某个地方读到,如果静态构造函数/初始化器等待线程完成,它们可能会在 c# 中陷入死锁。这和这个有关系吗?

我需要摆脱这个警告,我该怎么做。我无法使成员非静态,因为它由静态函数使用。在这种情况下我该怎么办,需要帮助。

您可以将其隐藏在属性后面并在首次使用时对其进行初始化(不是线程安全的);

class A
{
    static SomeClass aField;
    static SomeClass aProperty
    {
        get
        {
           if (aField == null) { aField = new Someclass("asfae"); }
           return aField;
        }
    }
}

或使用延迟(线程安全):

class A
{
    static Lazy<SomeClass> a = new Lazy<SomeClass>(() => new Someclass("asfae"));
}

。或者这个非常冗长的线程安全版本:)

class A
{
    static SomeClass aField;
    static object aFieldLock = new object();
    static SomeClass aProperty
    {
        get
        {
           lock (aFieldLock)
           {
               if (aField == null) { aField = new Someclass("asfae"); }
               return aField;
           }
        }
    }
}

通过将其初始化为静态字段,它的行为与静态构造函数中的行为相同,即它可能在第一次实例化类的实例时被初始化,但可能会更早发生。如果你想更好地控制字段初始化的确切时间,你可以使用 Lazy<T> ,例如:

{
   static Lazy<SomeClass> a = new Lazy<SomeClass>(() => new Someclass("asfae"));  
}

这样,您就知道 SomeClass 的初始化只会在第一次访问字段并调用其Value属性时发生。

我认为要了解您的问题,您需要了解静态构造函数和类型初始值设定项之间的区别,Jon Skeet 有一篇关于这个问题的很棒的文章:

http://csharpindepth.com/Articles/General/Beforefieldinit.aspx

关键是以下构造不一样,行为上也存在差异:

class Test
{
    static object o = new object();
}
class Test
{
    static object o;
    static Test()
    {
        o = new object();
    }
} 

在任何情况下,您都可以尝试为类创建一个静态构造函数,以便能够对此初始化进行更多控制,并且警告可能会消失。

如果该成员仅由静态方法

使用,并且仅由此方法使用,则我建议您将其放在此静态方法而不是类成员的作用域中。

最新更新