GetField 和 GetValue 等反射方法是否执行 ECMA 规范术语中的 "referencing" 或 "access"?

Does reflection methods such as GetField and GetValue perform "referencing" or "access" in ECMA specification terms?

我真正想知道的是哪些反射方法会触发类型初始化?我有点不清楚。具体来说,如果将提到的两个方法 GetField 和 GetValue 应用于静态字段,是否会触发类型初始化?我已经尝试调查此事,据我所知,执行诸如引用或访问静态字段的操作 触发所有静态字段的类型初始化。下面我引用了我认为相关的规范部分,但是 "referencing" 和 "access" 等措辞的使用正是我犹豫的地方:
哪些操作实际上符合 "access"?
获取字段的 FieldInfo 元数据是否算作 "referencing" 或 "accessing" 字段?

请帮我找到规范的相关部分,这样我就知道我的代码*是安全和规范的。合规并且不仅仅是 "happen to work" 因为一些未记录的实施细节或因为行星恰好对齐。

*我的代码通过了测试,但依赖于类型初始化行为。我的代码没有在这里显示,因为它很冗长,问题不是关于我只是想要 "your code looks ok" 回复,而是我想了解如何以及为什么这样我可以评估我的代码是否符合规范。我自己是否合规,并且(假设它是合规的)说明我可以或不能对其进行哪些更改,而不必每次都问一个新问题。


到目前为止,我知道以下规范,其中使用了上述术语 "referencing" 和 "access":

我知道 ECMA-334 (C# 语言规范),静态字段初始化,第 17.4.5.1 节

If a static constructor (§17.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

也知道 ECMA-334 (C# 语言规范),静态构造函数,第 17.11 节

The static constructor for a non-generic class executes at most once in a given application domain. The static constructor for a generic class declaration executes at most once for each closed constructed type constructed from the class declaration (§25.1.5). The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • An instance of the class is created.
  • Any of the static members of the class are referenced.

If a class contains the Main method (§10.1) in which execution begins, the static constructor for that class executes before the Main method is called. If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor (§17.4.5).

更相关的是 ECMA-335 (CLI 规范),Class 类型定义,第一部分,第 8.9.5 节

[...] The semantics of when and what triggers execution of such type initialization methods, is as follows:

  1. A type can have a type-initializer method, or not.
  2. A type can be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed semantic BeforeFieldInit).
  3. If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field defined for that type.
  4. If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e., is triggered by):
    a. first access to any static field of that type, or
    b. first invocation of any static method of that type, or
    c. first invocation of any instance or virtual method of that type if it is a value type or
    d. first invocation of any constructor for that type.
  5. Execution of any type's initializer method will not trigger automatic execution of any initializer methods defined by its base type, nor of any interfaces that the type implements.

相关的 MSDN 链接:
Type.GetField Method
FieldInfo Class
FieldInfo.GetValue Method

What I really want to know is which reflection methods will trigger type initialization?

[...]

Specifically, will the two mentioned methods, GetField and GetValue, trigger type initialization if applied to static fields?

FieldInfo.GetValue 触发类型初始化。是从实验观察中得来的。这一切都取决于实施,并且不会有任何证据。它不一定在所有情况下都有效,因为 Reflection 不需要遵循任何规范,因为规范不涵盖 Reflection。有一些 signs 你可以获得未初始化的字段,但我无法生成实现它的代码。

typeof()Type.GetTypeType.GetField 很可能不会触发类型初始化。但同样,这是来自观察。

如果您需要确保您的类型初始值设定项将在任何特定时间被调用 at/before,您需要调用 RuntimeHelpers.RunClassConstructor 方法。这是保证类型初始化程序将被调用的唯一方法,并且在应用程序域的生命周期中仅调用一次。

What actions actually qualifies as "access"?

None 这些操作,因为反射再次未包含在规范中,因此这些术语不适用于此处。

Does getting FieldInfo metadata for a field count as "referencing" or "accessing" the field?

都没有。

从规范上看不清楚,但我是这样理解“访问”和“引用”的区别的:

  • 访问是当你调用这个成员(方法或属性)或get/set它的值(字段)
  • 方法引用一个成员,当方法的主体具有对该成员的访问表达式时。

PS: 还不清楚你在问什么,你试图解决什么具体问题。