为什么CLR不总是调用值类型构造函数 [英] Why doesn't the CLR always call value type constructors

查看:109
本文介绍了为什么CLR不总是调用值类型构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于Value类型中的类型构造函数的问题.这个问题的灵感来自Jeffrey Richter通过C#第三版在CLR中写的东西,他说(在第195页-第8章),您永远不应该在值类型中实际定义类型构造函数,因为在某些情况下CLR不会调用它.

I have a question concerning type constructors within a Value type. This question was inspired by something that Jeffrey Richter wrote in CLR via C# 3rd ed, he says (on page 195 - chapter 8) that you should never actually define a type constructor within a value type as there are times when the CLR will not call it.

因此,例如(嗯...实际上是Jeffrey Richters的例子),即使通过查看IL也无法弄清楚为什么在以下代码中未调用类型构造函数:

So, for example (well...Jeffrey Richters example actually), I can't work out, even by looking at the IL, why the type constructor is not being called in the following code:

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
    }
}

因此,将以下规则应用于类型构造函数,我根本看不出为什么根本没有调用上面的值类型构造函数.

So, applying the following rules for type constructors I just can't see why the value type constructor above is not called at all.

  1. 我可以定义一个静态值类型构造函数来设置类型的初始状态.
  2. 一种类型最多只能有一个构造函数-没有默认的构造函数.
  3. 类型构造函数是隐式私有的
  4. JIT编译器检查类型的类型构造函数是否已在此AppDomain中执行.如果不是,它将发出对本机代码的调用,否则不会调用,因为它知道类型已经被初始化"了.

所以...我无法弄清为什么看不到正在构造的这种类型的数组.

So...I just can't work out why I can't see this type array being constructed.

我的最佳猜测是:

  1. CLR构造类型数组的方式.我本以为在创建第一个项目时会调用静态构造函数
  2. 构造函数中的代码未初始化任何静态字段,因此将其忽略.我已经尝试过在构造函数中初始化私有静态字段,但该字段仍为默认0值-因此未调用构造函数.
  3. 或者...由于设置了公共Int32,编译器正在某种程度上优化了构造函数调用,但这充其量只是一个模糊的猜测!

最佳实践等方面,我只是对它超级感兴趣,因为我希望自己了解为什么它不被调用.

Best practices etc asside, I am just super intrigued by it as I want to be able to see for myself why it doesn't get called.

我在下面对自己的问题添加了一个答案,只是引用了杰弗里·里希特(Jeffrey Richter)所说的话.

I added an answer to my own question below, just a quote of what Jeffrey Richter says about it.

如果任何人有任何想法,那就太好了. 非常感谢, 詹姆斯

If anyone has any ideas then that would be brilliant. Many thanks, James

推荐答案

The Microsoft C#4 Spec has changed slightly from previous versions and now more accurately reflects the behaviour that we're seeing here:

11.3.10静态构造函数

结构的静态构造函数如下 大部分与类相同的规则. 静态构造函数的执行 对于一个结构类型是由 以下发生的第一个事件 在应用程序域中:

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:

  • 引用了struct类型的静态成员.
  • 调用显式声明的struct类型的构造函数.

创建默认值 (§11.3.4)的结构类型不 触发静态构造函数. (一个 例子是初始值 数组中的元素数.)

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规范所以看起来C#3违反了它自己的规范. C#4规范已与C#3和4的实际行为紧密结合.

The ECMA Spec and the Microsoft C#3 Spec both have an extra event in that list: "An instance member of the struct type is referenced". So it looks as if C#3 was in contravention of its own spec here. The C#4 Spec has been brought into closer alignment with the actual behaviour of C#3 and 4.

编辑...

经过进一步调查,似乎几乎所有实例成员访问 直接字段访问都将触发静态构造函数(至少在当前的Microsoft C#3和4实现中).

After further investigation, it appears that pretty much all instance member access except direct field access will trigger the static constructor (at least in the current Microsoft implementations of C#3 and 4).

因此,与C#4规范中的规则相比,当前的实现与ECMA和C#3规范中给出的规则更紧密相关:访问所有实例成员 except <时,C#3规则已正确实现./em>字段; C#4规则仅 正确实施以用于字段访问.

So the current implementations are more closely correlated with the rules given in the ECMA and C#3 specs than those in the C#4 spec: the C#3 rules are implemented correctly when accessing all instance members except fields; the C#4 rules are only implemented correctly for field access.

(当涉及到与静态成员访问和显式声明的构造函数有关的规则时,所有规范都是一致的-显然是正确实现的.)

(The different specs are all in agreement -- and apparently correctly implemented -- when it comes to the rules relating to static member access and explicitly declared constructors.)

这篇关于为什么CLR不总是调用值类型构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆