C#如何知道何时运行静态构造函数?

12

我不相信生成的代码会在每次访问静态成员(包括函数)时都检查类是否已初始化。我认为每次访问都进行检查效率很低。我查看了 ECMA 334 中的 §17.11,它说:

触发静态构造函数执行的第一个应用程序域内事件是以下事件中的任意一个:

  • 创建类的实例。
  • 引用该类的任何静态成员。

看起来如何确定何时发生“第一次”并未定义。我无法想到任何方法,只能每次都进行检查。有什么方法可以解决这个问题?


3
相关的,对于静态情况:http://csharpindepth.com/Articles/General/Beforefieldinit.aspx - 这是一个非常重要的文章。 - Marc Gravell
这不就是在第一次调用后将函数指针设置为不同的位置的问题吗?起初它指向类加载器或其他什么,然后指向函数体... - user1096188
1
@Marc:这讨论的是在允许访问静态成员之前调用静态构造函数的问题,而不是如何检测第一次访问。 - Ben Voigt
@Ben - k;重新措辞。然而,对这个领域感兴趣的任何人仍将从文章中受益-因此我保留了链接。 - Marc Gravell
我认为“...由以下事件中的第一个触发...”是指如果这些事件中的任何一个发生,那么静态构造函数就会被调用。这段文本可能更加简明扼要 - 我认为它有点含糊不清。 - RobertMS
@Marc:这对我来说很有趣。我不知道初始化器(在4.0中,链接在这篇文章中http://msmvps.com/blogs/jon_skeet/archive/2010/01/26/type-initialization-changes-in-net-4-0.aspx)会这样做。然而,我仍然无法弄清楚它是否会在每次静态使用/使用new时检查变量(甚至调用函数ptr)。 (假设它之前没有在函数中被调用过) - user34537
2个回答

17

当你需要解决一个问题时,一个好的技巧是:解决一个更难的问题,这样你小问题的解决方案就可以通过解决更难的问题来解决。

CLR需要解决一个更加困难的问题:在每次第一次调用方法之前,必须精确地运行Jitter。如果CLR能够解决这个问题,那么它显然可以解决检测静态构造函数何时需要运行的相对较简单的子问题。

也许你的问题应该是“Jitter如何知道何时为方法进行JIT编译?”


有趣。我只是假设非嵌入式系统上的JIT会立即对所有内容进行JIT编译,并等待加载新的dll。我假设嵌入式系统使用预先编译。这是一个错误的假设,特别是当大量代码参与时。对于这个想法点赞。 - user34537
1
@acidzombie24 实际上,有些嵌入式系统根本不使用JIT/AOT - Micro Framework是一个IL解释器(祈祷我没有搞反...) - Marc Gravell
一些系统如 .Net Compact Framework JIT 只能处理基本的事情,例如获取属性就是一个函数调用。 - Lukasz Madon
你没有回答这个问题。 - nightcoder

5

当您在运行时生成代码时,有很多选项。您可以调用一个空的函数指针,捕获访问冲突,运行静态构造函数,编译属性获取器,更新函数指针并继续执行。或者让属性获取器调用一个帮助函数来运行静态构造函数,并重新编写获取器代码,不再需要帮助函数调用。或在每次访问静态成员时插入检查点,如果命中,则重新编译调用函数并删除检查点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接