Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C中静态构造函数的潜在陷阱#_C#_.net_Static_Clr - Fatal编程技术网

C# C中静态构造函数的潜在陷阱#

C# C中静态构造函数的潜在陷阱#,c#,.net,static,clr,C#,.net,Static,Clr,我的问题是在重构一个只包含要声明为static类的静态方法的类之后,在启动应用程序时遇到了奇怪的问题 我没有进行任何彻底的调查,但似乎由于某种原因,静态构造函数中的一些调用没有完成 因此,我想知道在C#中使用静态构造函数时会有哪些陷阱?更具体地说,是否有任何事情应该不惜一切代价避免,而不是在静态构造函数中使用?是的,存在一些陷阱,主要与初始化类的时间有关。基本上,带有静态构造函数的类不会被标记为beforefieldinit标志,这允许运行时稍后对其进行初始化 查看更多详细信息。静态构造函数有几

我的问题是在重构一个只包含要声明为
static
类的静态方法的类之后,在启动应用程序时遇到了奇怪的问题

我没有进行任何彻底的调查,但似乎由于某种原因,静态构造函数中的一些调用没有完成


因此,我想知道在C#中使用静态构造函数时会有哪些陷阱?更具体地说,是否有任何事情应该不惜一切代价避免,而不是在静态构造函数中使用?

是的,存在一些陷阱,主要与初始化类的时间有关。基本上,带有静态构造函数的类不会被标记为
beforefieldinit
标志,这允许运行时稍后对其进行初始化


查看更多详细信息。

静态构造函数有几个陷阱。例如,如果是静态构造函数,则无论何时访问其任何成员,都会继续获得
TypeInitializationException

如果静态构造函数抛出异常,运行时将不会再次调用它,并且在程序运行的应用程序域的生命周期内,该类型将保持未初始化状态

通常,静态类应该只在无状态场景中使用,在这种场景中,您不需要任何初始化。如果需要初始化类,最好使用,可以在首次访问时使用:

public class MyClass
{
    private static readonly Lazy<MyClass> current = 
        new Lazy<MyClass>(() => new MyClass());

    public static MyClass Current
    {
        get { return current.Value; }
    }

    private MyClass()
    {
        // Initialization goes here.
    }

    public void Foo()
    {
        // ...
    }

    public void Bar()
    {
        // ...
    }
}

static void Main(string[] args)
{
    MyClass.Current.Foo();   // Initialization only performed here.
    MyClass.Current.Bar();
    MyClass.Current.Foo();
}

在上面的示例中,新线程需要访问定义为其回调的空匿名函数
{}
。但是,由于匿名函数在幕后编译为
MyClass
的另一个私有方法,因此在
MyClass
类型初始化之前,新线程无法访问它。而且,由于
MyClass
静态构造函数需要等待新线程首先完成(因为
thread.Join()
),死锁随之发生。

这不是问题的答案,但是对于注释来说太长了,所以我在这里提供它

由于我不知道静态类构造,因此我使用以下方案(简化)为我提供了单例:

public class SomeSingleton {
    static _instance;
    static public SomeSingleton Instance {
        get {
            if (_instance==null) {
                _instance=new SomeSingleton();
            }
            return _instance;
        }
    }
}
以后,你用

SomeSingleton.Instance.MyProp = 3;
第一次使用
实例
成员将构造您的单例


我想这是可以的,因为如果有许多这样的类是按正确的顺序进行实例化的,那么单例就可以了。

它没有回答这个问题。。。静态类与单例不同(例如,不能将静态类作为参数传递,这可以通过单例来实现)。您的初始化不是线程安全的。如果多个线程同时访问
Instance
属性,则它们可能会得到不同的“singleton”实例。在特定情况下,这可能是一个问题,也可能不是,但它总体上打破了单例范式。如果您在.NET4(或更高版本)上,您应该切换到
惰性
;如果没有,则应该考虑使用<代码>锁定>代码>来同步初始化。除了构造函数之外,还有什么异常吗?例如,什么可以解释我所经历的类似“死锁”的情况?静态类型是否在幕后涉及任何锁定?第一个示例中的锁定与这些行之间是否有任何区别<代码>私有静态只读惰性当前;静态MyClass{current=new Lazy(()=>new MyClass());}(很抱歉,似乎无法正确设置格式:)@Mark:我相信两者是等效的。静态构造函数所做的唯一一件事就是将
Lazy
分配给静态字段(不初始化它),这样它就不会失败(即使
MyClass()
构造函数抛出异常)。在这两种情况下,只有在第一次调用
MyClass.Current
时才初始化单例。感谢完整的示例!对于那些想知道上述单例是否是线程安全的和“最佳”解决方案(这是隐含的,但我希望是明确的)的人来说,答案是肯定的。我很高兴看到你的编辑。我正试图做这件事,却不明白为什么它不起作用。非常感谢!
SomeSingleton.Instance.MyProp = 3;