Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

What I really want to know is which reflection methods will trigger type initialization? It's a bit unclear to me. Specifically, will the two mentioned methods, GetField and GetValue, trigger type initialization if applied to static fields? I've already tried looking into the matter, and as far as I understand performing actions such as referencing or accessing static fields will trigger type initialization of all static fields. Below I have quoted sections of the specification that I think are relevant, but the use of wording such as "referencing" and "access" is precisely where my hesitation stems:
What actions actually qualifies as "access"?
Does getting FieldInfo metadata for a field count as "referencing" or "accessing" the field?

Please help me find the relevant parts of the specifications so I know that my code* is safe and spec. compliant and doesn't simply "happen to work" because of some undocumented implementation detail or because the planets happen to be aligned just right.

*My code passes testing but relies on type initialization behavior. My code is not shown here because it is verbose and the question is not about me just wanting a "your code looks ok" reply, but rather I want to learn how and why such that I can asses whether my code is spec. compliant or not myself, and (assuming it is compliant) reason about what changes I can and cannot make to it without having to ask a new question every time I do so.


So far I know about the following pieces of the specifications, which uses the aforementioned terms "referencing" and "access":

I know about ECMA-334 (C# language specification), Static field initialization, section 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.

Also know about ECMA-334 (C# language specification), Static constructors, section 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).

And more relevantly ECMA-335 (CLI specification), Class type definition, part I, section 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.

Related MSDN links:
Type.GetField Method
FieldInfo Class
FieldInfo.GetValue Method

like image 569
AnorZaken Avatar asked Jun 01 '17 16:06

AnorZaken


1 Answers

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 triggers the type initialization. It's from the experiment observation. It all depends on an implementation, and there will be no proofs. It will not necessary work in all cases, as Reflection does not need to follow any specs, as the specifications are not covering Reflection. There are some signs that you can get a uninitialized field, but I could not produce the code to make it happen.

typeof(), Type.GetType, and Type.GetField most likely do not trigger the type initialization. But again, this is from an observation.

If you need to make sure that your type initializer will be called at/before any particular time, you need to call RuntimeHelpers.RunClassConstructor method. This is the only method which guarantees that the type initializer will be invoked and only once in a lifetime of an app domain.

What actions actually qualifies as "access"?

None of these actions, as again reflections is not covered by the specs and so these terms do not apply here.

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

Neither.

It's not clear from the specification, but this is how I understand the difference between "accessing" and "referencing":

  • Access is when you invoke this member (method or property) or get/set its value (field)
  • A method references a member when the body of the method has an access expression to this member.

PS: It's still not clear what you are asking and what particular problem you try to solve.

like image 65
hazzik Avatar answered Nov 01 '22 21:11

hazzik