我有一个关于值类型中的类型构造函数的问题。这个问题的灵感来自 Jeffrey Richter 通过 C# 3rd ed 在 CLR 中写的东西,他说(在第 195 页 - 第 8 章)你永远不应该在值类型中定义类型构造函数,因为有时 CLR 不会调用
因此,例如(好吧......实际上是 Jeffrey Richters 的例子),即使通过查看 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
}
}
所以,对类型构造函数应用以下规则我只是不明白为什么上面的值类型构造函数根本没有被调用。
- 我可以定义一个静态值类型构造函数来设置类型的初始状态。
- 一个类型只能有一个构造函数——没有默认构造函数。
- 类型构造函数是隐式私有(private)的
- JIT 编译器检查该类型的类型构造函数是否已在此 AppDomain 中执行。如果不是,它会发出对 native 代码的调用,否则它不会发出调用,因为它知道该类型已经“初始化”。
所以...我只是想不通为什么我看不到正在构造的这种类型数组。
我最好的猜测是它可能是:
- CLR 构造类型数组的方式。我本以为在创建第一个项目时会调用静态构造函数
- 构造函数中的代码没有初始化任何静态字段,所以它被忽略了。我已经尝试在构造函数中初始化私有(private)静态字段,但该字段仍然是默认的 0 值 - 因此不会调用构造函数。
- 或者...由于设置了公共(public) Int32,编译器以某种方式优化了构造函数调用 - 但这充其量只是一个模糊的猜测!!
抛开最佳实践等不谈,我只是对它非常感兴趣,因为我想亲眼看看为什么它没有被调用。
编辑:我在下面添加了我自己的问题的答案,只是引用了 Jeffrey Richter 所说的话。
如果有人有任何想法,那就太好了。 非常感谢, 詹姆斯
最佳答案
Microsoft C#4 Spec与以前的版本略有不同,现在更准确地反射(reflect)了我们在这里看到的行为:
11.3.10 Static constructors
Static constructors for structs follow most of the same rules as for classes. The execution of a static constructor for a struct type is triggered by the first of the following events to occur within an application domain:
- A static member of the struct type is referenced.
- An explicitly declared constructor of the struct type is called.
The creation of default values (§11.3.4) of struct types does not trigger the static constructor. (An example of this is the initial value of elements in an array.)
ECMA Spec和 Microsoft C#3 Spec两者在该列表中都有一个额外事件:“引用了结构类型的实例成员”。 所以看起来 C#3 在这里违反了它自己的规范。 C#4 规范已与 C#3 和 4 的实际行为更加一致。
编辑...
经过进一步调查,似乎几乎所有实例成员访问直接字段访问都会触发静态构造函数(至少在 C#3 和 4 的当前 Microsoft 实现中是这样)。 p>
因此,当前的实现与 ECMA 和 C#3 规范中给出的规则的相关性比 C#4 规范中的规则更紧密:在访问所有实例成员时,C#3 规则得到了正确的实现 except 字段; C#4 规则仅正确实现了字段访问。
(当涉及到与静态成员访问和显式声明的构造函数相关的规则时,不同的规范都是一致的——并且显然已正确实现。)
关于c# - 为什么 CLR 不总是调用值类型构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3246078/