简体   繁体   English

beforefieldinit 标志有什么作用?

[英]What does beforefieldinit flag do?

What does beforefieldinit flag do? beforefieldinit 标志有什么作用? When I look into the IL of my class I see this flag but I don't know what this flag is actually doing?当我查看我的 class 的 IL 时,我看到了这个标志,但我不知道这个标志实际上在做什么?

See my article on this very issue.请参阅 我关于这个问题的文章

Basically, beforefieldinit means "the type can be initialized at any point before any static fields are referenced."基本上, beforefieldinit意味着“可以在引用任何 static 字段之前的任何时候初始化类型。” 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.从理论上讲,这意味着它可以非常延迟地初始化 - 如果您调用不涉及任何字段的 static 方法,则 JIT 不需要初始化类型。

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.在实践中,这意味着 class 的初始化时间比其他情况要早 - 它可以在可能使用它的第一个方法开始时进行初始化。 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.将此与应用beforefieldinit的类型进行比较,其中类型初始化必须在第一次实际使用之前立即发生。

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).如果这两种类型都应用了beforefieldinit (在 C# 中默认情况下它们会这样做,除非该类型具有 static 构造函数),那么它们将在DoSomething方法的开始时被初始化(通常 - 不能保证)。 If they don't have beforefieldinit then only one of them will be initialized, based on the flag.如果他们没有beforefieldinit ,那么只有其中一个会被初始化,基于标志。

This is why it's common to use a static constructor (even an empty one!) when implementing the singleton pattern .这就是为什么在实现 singleton 模式时通常使用 static 构造函数(甚至是空的构造函数!)的原因。

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.如果标记为 BeforeFieldInit,则该类型的初始化方法在或之前的某个时间执行,首先访问为该类型定义的任何 static 字段。

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.如果未标记 BeforeFieldInit,则在第一次访问任何 static 或该类型的实例字段,或第一次调用任何 static、该类型的实例或虚拟方法时执行该类型的初始化方法。

Quote from “ CA1810: Initialize reference type static fields inline (code analysis) - .NET |引用自“ CA1810:初始化引用类型 static 字段内联(代码分析)- .NET | Microsoft Docs ” with emphasis mine and TL;DR at the bottom: Microsoft Docs ”,重点是 mine 和 TL;DR 在底部:

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 构造函数时,即时 (JIT) 编译器会检查每个 static 方法和该类型的实例构造函数,以确保之前调用了 ZA81259CEF8E959C3297ZD456E 构造函数。 Static initialization is triggered when any static member is accessed or when an instance of the type is created.当访问任何 static 成员或创建该类型的实例时,将触发 Static 初始化。 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.但是,如果您声明该类型的变量但不使用它,则不会触发 static 初始化,如果初始化更改全局 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 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.当 JIT 编译器遇到beforefieldinit标志时,大多数时候不会添加 static 构造函数检查。 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. Static 初始化保证在访问任何 static 字段之前的某个时间发生,但不会在调用 static 方法或实例构造函数之前发生。 Note that static initialization can occur at any time after a variable of the type is declared.请注意,static 初始化可以在声明该类型的变量后的任何时间进行。

Static constructor checks can decrease performance. Static 构造函数检查会降低性能。 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. 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. beforefieldinit行为适用于这些和大多数其他类型。 It is only inappropriate when static initialization affects global state and one of the following is true:仅当 static 初始化影响全局 state 并且以下情况之一为真时才不合适:

  • The effect on global state is expensive and is not required if the type is not used.对全局 state 的影响是昂贵的,如果不使用该类型则不需要。

  • The global state effects can be accessed without accessing any static fields of the type.无需访问该类型的任何 static 字段即可访问全局 state 效果。

TL;DR: beforefieldinit flag helps avoid static constructor checks, which helps in performance (since the checks can affect performance). TL;DR: beforefieldinit标志有助于避免 static 构造函数检查,这有助于提高性能(因为检查会影响性能)。 It does this by telling the JIT to run static constructors before the actual static field usage.它通过告诉 JIT 在实际使用 static 字段之前运行 static 构造函数来实现这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM