5

我正在处理一些类似这样的代码:

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

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

“已从静态构造函数和/或静态初始化程序调用了 Someclass ctor”

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

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

4

3 回答 3

1

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

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;
           }
        }
    }
}
于 2014-03-05T11:44:50.653 回答
0

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

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

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

于 2014-03-05T11:48:50.830 回答
0

我认为要了解您的问题,您需要了解静态构造函数和类型初始化程序之间的区别,Jon Skeet 有一篇关于此问题的精彩文章:

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

关键是以下构造不相同,并且行为有所不同:

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

class Test
{
    static object o;

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

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

如果该成员仅由静态方法使用,并且仅由该方法使用,我建议您将其放在此静态方法的范围内,而不是作为类成员。

于 2014-03-05T11:51:01.963 回答