我有一个关于值类型中的类型构造函数的问题。这个问题是受 Jeffrey Richter 在《CLR via C# 第三版》中写的一些东西启发的,他在第8章的第195页上说,你不应该在值类型中实际定义类型构造函数,因为有时候CLR不会调用它。
例如(好吧...实际上是Jeffrey Richter的例子),即使通过查看IL代码,我也无法确定以下代码中为什么未调用类型构造函数:
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("This never gets displayed");
}
public Int32 _x;
}
public sealed class Program
{
static void Main(string[] args)
{
SomeValType[] a = new SomeValType[10];
a[0]._x = 123;
Console.WriteLine(a[0]._x); //Displays 123
}
}
应用以下类型构造函数规则,我就是无法理解为什么上面的值类型构造函数根本没有被调用。
- 我可以定义一个静态的值类型构造函数来设置类型的初始状态。
- 一个类型最多只能有一个构造函数 - 没有默认构造函数。
- 类型构造函数在隐式情况下是私有的
- JIT编译器检查类型的类型构造函数是否已经在此AppDomain中执行。如果没有,则它会生成对本机代码的调用,否则不会,因为它知道该类型已经'初始化'。
所以...我就是想不明白为什么我看不到这个类型数组被构造。
我最好的猜测是:
- CLR构造类型数组的方式。我原以为当创建第一个项目时,静态构造函数会被调用
- 构造函数中的代码没有初始化任何静态字段,因此被忽略了。我尝试在构造函数中初始化私有静态字段,但该字段仍保持默认的0值 - 因此构造函数没有被调用。
- 或者...编译器由于设置了公共Int32而对构造函数调用进行了优化 - 但这只是模糊的猜测!
最佳实践等不予考虑,我只是对此深感兴趣,因为我想自己看看为什么它没有被调用。
编辑:我在下面添加了自己的答案,只是引用了Jeffrey Richter关于此问题的说法。
如果有人有任何想法,那将是很棒的。 非常感谢, 詹姆斯
Console.WriteLine
——但它没有被调用,尽管规范似乎表明它应该被调用。现在,如果编译器/即时编译器可以确定何时没有副作用——也许他们已经可以了——然后避免调用,那就是智能了。 - LukeH