【问题标题】:Static variable initialization using new gives a code hazard使用 new 进行静态变量初始化会带来代码风险
【发布时间】:2014-04-07 10:27:51
【问题描述】:

我正在编写一些类似这样的代码:

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

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

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

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

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

【问题讨论】:

  • 那个静态字段的用途是什么?

标签: c# constructor static static-members static-constructor


【解决方案1】:

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

class A
{
    static SomeClass aField;

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

或使用 Lazy(线程安全):

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;
           }
        }
    }
}

【讨论】:

  • 不支持使用.net3.5lazy,不想做非线程安全的解决方案。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    我认为要了解您的问题,您需要了解静态构造函数和类型初始化程序之间的区别,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();
        }
    } 
    

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

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

    【讨论】:

    • 该成员被其他方法使用,其中一些方法也不是静态的。
    • 我使用的是 .net 3.5,所以使用惰性不是一个选项,因为它不受支持,我尝试了静态构造函数,但我仍然收到警告。还有其他想法吗?
    • 由于您使用的是静态成员,因此存在一些风险,我会将此警告理解为提示,但这并不意味着您的代码是错误的。如果您需要这个静态成员并且知道如何使用它,那么它不会损害您的应用程序。您的应用程序是多线程的吗?如果不是多线程的,你不必担心这个。
    猜你喜欢
    • 2010-12-26
    • 2012-08-19
    • 2011-08-22
    • 2010-12-22
    • 2011-01-21
    • 2015-12-09
    • 2021-10-28
    • 2017-05-13
    • 2010-12-11
    相关资源
    最近更新 更多