What does beforefieldinit flag do? When I look into the IL of my class I see this flag but I don't know what this flag is actually doing?
See my article on this very issue.
Basically, beforefieldinit
means "the type can be initialized at any point before any static fields are referenced." In theory that means it can be very lazily initialized - if you call a static method which doesn't touch any fields, the JIT doesn't need to initialize the type.
In practice it means that the class is initialized earlier than it would be otherwise - it's okay for it to be initialized at the start of the first method which might use it. Compare this with types which don't have beforefieldinit
applied to them, where the type initialization has to occur immediately before the first actual use.
So, suppose we have:
public static void DoSomething(bool which)
{
if (which)
{
FirstType.Foo();
}
else
{
SecondType.Bar();
}
}
If both types have beforefieldinit
applied to them (which in C# they do by default unless the type has a static constructor) then they'll both be initialized at the start of the DoSomething
method (usually - it's not guaranteed). If they don't have beforefieldinit
then only one of them will be initialized, based on the flag.
This is why it's common to use a static constructor (even an empty one!) when implementing the singleton pattern.
SecondType
will be (very very slightly) faster, because it allows the JIT more leeway in terms of how it handles initialization. Forget about the beforefieldinit
details; stick to just the C# abstraction layer: the presence of a static constructor makes a guarantee about exactly when the type will be initialized, which means the JIT can't generate code that's quite as optimized. –
Lyndsaylyndsey Looks like it is going to change in 4.6
beforefieldinit
or not)? –
Gage Quote from “CA1810: Initialize reference type static fields inline (code analysis) - .NET | Microsoft Docs” with emphasis mine and TL;DR at the bottom:
When a type declares an explicit static constructor, the just-in-time (JIT) compiler adds a check to each static method and instance constructor of the type to make sure that the static constructor was previously called. Static initialization is triggered when any static member is accessed or when an instance of the type is created. However, static initialization is not triggered if you declare a variable of the type but do not use it, which can be important if the initialization changes global state.
When all static data is initialized inline and an explicit static constructor is not declared, Microsoft intermediate language (MSIL) compilers add the
beforefieldinit
flag and an implicit static constructor, which initializes the static data, to the MSIL type definition.When the JIT compiler encounters the
beforefieldinit
flag, most of the time the static constructor checks are not added. Static initialization is guaranteed to occur at some time before any static fields are accessed but not before a static method or instance constructor is invoked. Note that static initialization can occur at any time after a variable of the type is declared.Static constructor checks can decrease performance. Often a static constructor is used only to initialize static fields, in which case you must only make sure that static initialization occurs before the first access of a static field. The
beforefieldinit
behavior is appropriate for these and most other types. It is only inappropriate when static initialization affects global state and one of the following is true:
The effect on global state is expensive and is not required if the type is not used.
The global state effects can be accessed without accessing any static fields of the type.
TL;DR: beforefieldinit
flag helps avoid static constructor checks, which helps in performance (since the checks can affect performance). It does this by telling the JIT to run static constructors before the actual static field usage.
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 first access to any static or instance field of that type, or first invocation of any static, instance or virtual method of that type.
© 2022 - 2024 — McMap. All rights reserved.