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:
- A type can have a type-initializer method, or not.
- A type can be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed semantic BeforeFieldInit).
- 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.
- 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.- 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
GetField()
) doesn't count as "accessing" or "referencing" the instance or type, but as soon as you callFieldInfo.GetValue()
it does. But that's an uneducated gut feeling for which I can't find confirmation, hence not posted as an answer. – Trifurcatethe question is not about finding ways to solve a specific problem
Your question is off-topic here. The answer to your question, however: reflection is not covered by the C# and CLI specifications and so, it all depends on an implementation. Based on my observation (which is the same as @CodeCaster): GetField does not trigger type initializer (static constructor), but FieldInfo.GetValue does. – Limes