换句话说,这个单例实现是线程安全的:

public class Singleton
{
    private static Singleton instance;

    private Singleton() { }

    static Singleton()
    {
        instance = new Singleton();
    }

    public static Singleton Instance
    {
        get { return instance; }
    }
}

当前回答

虽然所有这些答案都给出了相同的一般答案,但有一个警告。

记住,泛型类的所有潜在派生都被编译为单独的类型。因此,在为泛型类型实现静态构造函数时要谨慎。

class MyObject<T>
{
    static MyObject() 
    {
       //this code will get executed for each T.
    }
}

编辑:

下面是演示:

static void Main(string[] args)
{
    var obj = new Foo<object>();
    var obj2 = new Foo<string>();
}

public class Foo<T>
{
    static Foo()
    {
         System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));        
    }
}

在控制台:

Hit System.Object
Hit System.String

其他回答

静态构造函数保证每个应用程序域只触发一次,所以你的方法应该是OK的。然而,它在功能上与更简洁的内联版本没有什么不同:

private static readonly Singleton instance = new Singleton();

当您在惰性初始化事物时,线程安全更是个问题。

静态构造函数保证是线程安全的。 另外,看看DeveloperZen上关于Singleton的讨论: http://web.archive.org/web/20160404231134/http://www.developerzen.com/2007/07/15/whats-wrong-with-this-code-1-discussion/

虽然所有这些答案都给出了相同的一般答案,但有一个警告。

记住,泛型类的所有潜在派生都被编译为单独的类型。因此,在为泛型类型实现静态构造函数时要谨慎。

class MyObject<T>
{
    static MyObject() 
    {
       //this code will get executed for each T.
    }
}

编辑:

下面是演示:

static void Main(string[] args)
{
    var obj = new Foo<object>();
    var obj2 = new Foo<string>();
}

public class Foo<T>
{
    static Foo()
    {
         System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));        
    }
}

在控制台:

Hit System.Object
Hit System.String

虽然其他答案大多是正确的,但对于静态构造函数还有另一个警告。

根据ECMA-335通用语言的第二节10.5.3.3竞赛和死锁 基础设施

类型初始化本身不会产生死锁,除非有一些代码 从类型初始化器(直接或间接)显式调用 调用阻塞操作。

下面的代码导致死锁

using System.Threading;
class MyClass
{
    static void Main() { /* Won’t run... the static constructor deadlocks */  }

    static MyClass()
    {
        Thread thread = new Thread(arg => { });
        thread.Start();
        thread.Join();
    }
}

原作者是Igor Ostrovsky,见他的帖子在这里。

静态构造函数被锁定。当类型初始化式正在运行时,任何其他试图以触发类型初始化式的方式访问该类的线程都将阻塞。

但是,运行类型初始化式的线程可以访问未初始化的静态成员。因此,如果从UI线程运行类型初始化器,请确保不要从类型初始化器调用Monitor.Enter() (lock(){})或ManualResetEventSlim.Wait()——这些是“可中断”的等待,会导致事件循环运行,在类型初始化器尚未完成时执行程序的任意其他部分。

最好使用托管块而不是非托管块。WaitHandle。WaitOne WaitHandle。WaitAny WaitHandle。WaitAll、监控。输入、监控。TryEnter,线程。加入,GC。WaitForPendingFinalizers等等都对Thread有响应。中断和线程中止。同样,如果你的线程是在一个单线程的公寓,所有这些托管阻塞操作将正确泵消息在你的公寓当你的线程被阻塞: