请给我解释一下静态构造函数的用法。为什么,什么时候我们要创建一个静态构造函数,它是否可能重载一个?
当前回答
静态构造函数只调用创建的类的第一个实例。并用于执行在类的生命周期中只需要执行一次的特定操作。
其他回答
不,你不能让它过载;静态构造函数对于初始化与类型相关的任何静态字段(或任何其他每种类型的操作)非常有用——特别是对于将所需的配置数据读入只读字段等非常有用。
它在第一次需要时由运行时自动运行(那里的确切规则很复杂(参见“beforefieldinit”),并且在CLR2和CLR4之间有微妙的变化)。除非滥用反射,否则它保证最多运行一次(即使两个线程同时到达)。
来自静态构造函数(c#编程指南):
A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced. Static constructors have the following properties: A static constructor does not take access modifiers or have parameters. A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. A static constructor cannot be called directly. The user has no control on when the static constructor is executed in the program. A typical use of static constructors is when the class is using a log file and the constructor is used to write entries to this file. Static constructors are also useful when creating wrapper classes for unmanaged code, when the constructor can call the LoadLibrary method.
当静态字段相互依赖,初始化顺序很重要时,静态构造函数也非常有用。如果您通过一个改变字段顺序的格式化器/美化器运行代码,那么您可能会发现自己在意想不到的地方得到了空值。
示例:假设我们有这样一个类:
class ScopeMonitor
{
static string urlFragment = "foo/bar";
static string firstPart= "http://www.example.com/";
static string fullUrl= firstPart + urlFragment;
}
当您访问fullUr时,它将是“http://www.example.com/foo/bar”。
几个月后,您将清理代码并按字母顺序排列字段(假设它们是一个更大的列表的一部分,因此您没有注意到问题)。你有:
class ScopeMonitor
{
static string firstPart= "http://www.example.com/";
static string fullUrl= firstPart + urlFragment;
static string urlFragment = "foo/bar";
}
你的fullUrl值现在只是“http://www.example.com/”,因为urlFragment在设置fullUrl时还没有初始化。不好的。所以,你添加一个静态构造函数来处理初始化:
class ScopeMonitor
{
static string firstPart= "http://www.example.com/";
static string fullUrl;
static string urlFragment = "foo/bar";
static ScopeMonitor()
{
fullUrl= firstPart + urlFragment;
}
}
现在,不管字段的顺序是什么,初始化总是正确的。
可以使用静态构造函数初始化静态字段。在使用这些字段之前,它在一个不确定的时间运行。微软的文档和许多开发人员警告说,类型上的静态构造函数会带来巨大的开销。为了获得最佳性能,最好避免使用静态构造函数。 更新:你不能在同一个类中使用多个静态构造函数,但是你可以使用(最多)一个静态构造函数的其他实例构造函数。
为什么以及什么时候创建静态构造函数?
使用静态构造函数的一个特殊原因是创建一个“超级枚举”类。这里有一个(简单的,做作的)例子:
public class Animals
{
private readonly string _description;
private readonly string _speciesBinomialName;
public string Description { get { return _description; } }
public string SpeciesBinomialName { get { return _speciesBinomialName; } }
private Animals(string description, string speciesBinomialName)
{
_description = description;
_speciesBinomialName = speciesBinomialName;
}
private static readonly Animals _dog;
private static readonly Animals _cat;
private static readonly Animals _boaConstrictor;
public static Animals Dog { get { return _dog; } }
public static Animals Cat { get { return _cat; } }
public static Animals BoaConstrictor { get { return _boaConstrictor; } }
static Animals()
{
_dog = new Animals("Man's best friend", "Canis familiaris");
_cat = new Animals("Small, typically furry, killer", "Felis catus");
_boaConstrictor = new Animals("Large, heavy-bodied snake", "Boa constrictor");
}
}
你会非常相似地(在语法外观上)使用任何其他枚举:
Animals.Dog
与常规枚举相比,它的优点是可以轻松封装相关信息。一个缺点是不能在switch语句中使用这些值(因为它需要常量值)。