jam*_*ock 37 c# clr struct static-constructor typeinitializer
我有一个关于Value类型中的类型构造函数的问题.这个问题的灵感来自Jeffrey Richter在CLR中通过C#3rd ed编写的内容,他说(在第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
}
}
Run Code Online (Sandbox Code Playgroud)
因此,对类型构造函数应用以下规则,我只是看不出为什么根本没有调用上面的值类型构造函数.
所以......我无法理解为什么我看不到这个类型的数组正在被构造.
我最好的猜测是它可能是:
最佳实践等帮助,我只是对它非常感兴趣,因为我希望能够亲眼看到它为什么不被调用.
编辑:我在下面添加了我自己的问题的答案,只是引用杰弗里里希特所说的.
如果有人有任何想法,那将是辉煌的.非常感谢,詹姆斯
Luk*_*keH 17
在微软C#4规格略有上升,从以前的版本,现在更准确地改变,反映了我们在这里看到的行为:
11.3.10静态构造函数
结构的静态构造函数遵循与类相同的大多数规则.结构类型的静态构造函数的执行由应用程序域中发生的以下第一个事件触发:
- 引用了struct类型的静态成员.
- 调用显式声明的struct类型的构造函数.
结构类型的默认值(第11.3.4节)的创建不会触发静态构造函数.(这方面的一个例子是数组中元素的初始值.)
在ECMA规格和微软C#3规格都有在该列表中一个额外的事件:"在结构类型的实例成员引用".所以看起来C#3在这里违反了自己的规范.C#4规范已经与C#3和4的实际行为更加一致.
编辑...
在进一步调查之后,几乎所有实例成员访问除了直接字段访问之外都会触发静态构造函数(至少在C#3和4的当前Microsoft实现中).
因此,当前的实现与ECMA和C#3规范中给出的规则更密切相关,而不是C#4规范中的规则:当访问除字段之外的所有实例成员时,C#3规则正确实现; C#4规则仅适用于现场访问.
(当涉及到静态成员访问和显式声明的构造函数的规则时,不同的规范都是一致的 - 并且显然已经正确实现了.)
Mat*_*hen 11
从标准的§18.3.10开始(另请参阅C#编程语言书):
结构的静态构造函数的执行由应用程序域中发生的以下第一个事件触发:
- 引用了结构的实例成员.
- 引用结构的静态成员.
- 调用结构的显式声明构造函数.
[ 注意:结构类型的默认值(第18.3.4节)的创建不会触发静态构造函数.(这方面的一个例子是数组中元素的初始值.)end note ]
所以我同意你的观点,你的程序的最后两行应该各自触发第一条规则.
经过测试,共识似乎是它始终触发方法,属性,事件和索引器.这意味着它对除了字段之外的所有显式实例成员都是正确的.因此,如果为标准选择了微软的C#4规则,那么这将使他们的实施从大多数正确到大多数错误.