Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.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# - Fatal编程技术网

C# 它被称为第一个静态构造函数或私有构造函数

C# 它被称为第一个静态构造函数或私有构造函数,c#,C#,我在读一篇关于实现Singleton的教程,代码是 public class Singleton { private static readonly Singleton instance = new Singleton(); static Singleton() { Console.WriteLine("Static"); } private Singleton()

我在读一篇关于实现Singleton的教程,代码是

public class Singleton
    {
        private static readonly Singleton instance = new Singleton();

        static Singleton()
        {
            Console.WriteLine("Static");
        }
        private Singleton()
        {
            Console.WriteLine("Private");
        }

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

        public void DoSomething() {
            //this must be thread safe
        }
    }
当我编写Singleton.Instance时,输出是

私人
静止的

我原以为会这样

静态
私人的

原因是当我阅读MSDN教程时“

我看到公共构造函数是在静态构造函数之后调用的


为什么会有差异?

静态构造函数必须在类外的代码可以使用该类之前完成。但是语言规范必须允许实例构造函数在静态构造函数完成之前完成,因此您可以这样做,例如:

static Singleton()
{
    instance = new Singleton();
    // It has to be legal to use "instance" here
    Console.WriteLine("Static");
}
请注意,在您的示例中,基本上就是这样。字段初始值设定项实质上成为构造函数的一部分;他们只是先执行

生成的IL证实了这一点:

// Static constructor
Singleton..cctor:
IL_0000:  newobj      Singleton..ctor     //Calls private constructor first
IL_0005:  stsfld      Singleton.instance  //to create .instance
IL_000A:  nop         
IL_000B:  ldstr       "Static"
IL_0010:  call        System.Console.WriteLine
IL_0015:  nop         
IL_0016:  ret         

另请参见相关(但不是重复)问题和Eric Lippert典型的优秀答案:

对于单例,您不需要静态构造函数。创建一个对象,并使用
lock(object)
使用简单线程,这样只有一个线程可以访问您的方法。我从锁开始,已经阅读了足够多的文档,说明它们有多昂贵。因此,我选择了这段代码。@ViVi这个问题不是关于什么是更好的方法,而是为什么输出是
Private Static
。好question@ViVi:这取决于多种因素,主要是单例的构造函数有多昂贵,使用单例的可能性有多大。一个不常使用的单例,具有昂贵的构造函数,您可能希望使用
Lazy
返回,而不是直接初始化字段。否则,我将使用直场初始值设定项。无论哪种方式,您都可以让运行时或框架处理同步;自从
Lazy
被引入以来,一直没有一个很好的理由为单例编写显式锁定代码。@ViVi:请注意,您引用的Jon Skeet的文章甚至建议这样做。如果确实需要延迟初始化,请使用字段初始值设定项,或者使用
Lazy
。静态-->字段-->专用构造函数。我说对了吗?@Abdul:基本上,是的。这些都是在编译时确定的。它不像代码在静态构造函数中动态地确定它需要有效的实例。代码已经在那里了。但是是的,正是由于需要初始化静态构造函数中的字段,才导致调用实例构造函数。