非静态类中静态构造函数的作用是什么?

38

我注意到一个非静态类可以有一个静态构造函数:

public class Thing
{
    public Thing()
    {
        Console.WriteLine("non-static");
    }

    static Thing()
    {
        Console.WriteLine("static");
    }
}

当您初始化Thing实例时,静态构造函数会首先被调用。

输出:

静态

非静态

这样做有什么必要吗?您是否使用它来初始化非静态类型的实例上的静态字段?

在使用静态构造函数时有哪些需要考虑的事情?


4
你需要自己回答“初始化静态字段”的问题。在此处阅读有关静态构造函数的更多信息:http://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx。 - Rohit Vats
6个回答

41
你是用它来初始化非静态类型实例的静态字段吗? 基本上是这样,除了静态字段(或任何静态成员)与实例无关;它们与类型本身相关,无论它是静态类还是非静态类。 文档列出了一些静态构造函数的属性之一:文档
- 在创建第一个实例或引用任何静态成员之前自动调用静态构造函数以初始化类。 在这里,“before”意味着“紧接着”,以及其中哪个先发生。这是因为单个程序执行中每个类型仅调用一次静态构造函数。
有没有什么需要考虑的事情在使用静态构造函数时?
这里是给出的完整列表,可以让您了解在使用静态构造函数时会发生什么:
- 静态构造函数不需要访问修饰符或参数。 - 在创建第一个实例或引用任何静态成员之前, 自动调用静态构造函数以初始化类。 - 不能直接调用静态构造函数。 - 用户无法控制程序何时执行静态构造函数。 - 静态构造函数的典型用途是当该类使用日志文件时,构造函数用于向该文件写入条目。 - 当创建非托管代码的包装类时,静态构造函数也很有用,此构造函数可以调用LoadLibrary方法。 - 如果静态构造函数引发异常,则运行时不会再次调用它,并且类型将在应用程序域的生命周期内保持未初始化。

除了确保您不尝试访问非静态成员(因为您不在实例构造函数中),另一个主要考虑因素是静态构造函数始终在程序执行期间的特定时间调用。正如所述,您无法控制此行为,除非控制“创建第一个实例或引用任何静态成员”的时间。


4
来自MSDN 链接的内容如下:

在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。

正如您所说,它被用于初始化静态字段。你只需要考虑一件事情,非静态字段在创建类的实例之前不会被初始化。

1
  • 静态构造函数会在类的第一个实例创建之前自动调用。
  • 通过在构造函数定义前加上 static 关键字来声明。
  • 它不能带访问修饰符或任何参数。

1
你可以使用它来初始化或调用类的静态成员。

1
这是一个主观的答案,基于个人经验。但你也可以使用它来确保类外其他静态变量的初始化,而这些变量可能是你的类成员所依赖的。

0

但是在这里使用静态构造函数没有理由;你之前的代码通常比这个更可取,这使得使用静态构造函数成为一个不好的理由。 - Servy
在这种情况下,我同意这可能有些过度,但是想象一下Singleton具有需要添加的其他属性,所有这些属性都将在静态构造函数中设置,以及任何其他依赖项。然而,使用此方法生成单例完全是线程安全的,因为静态构造函数保证在每个应用程序域中运行一次,并且在创建类的任何实例之前运行。因此,这是一种简单的非锁定方式来生成单例。 - pb.
很少出现字段初始化程序不足以初始化静态字段的情况。就像在你的第一个示例中一样,静态字段初始化程序更短、更简单,而且同样功能强大。 - Servy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接