beforefieldinit 标志有什么作用?

发布于 2024-07-14 16:22:06 字数 71 浏览 8 评论 0原文

beforefieldinit 标志有什么作用? 当我查看班级的 IL 时,我看到这个标志,但我不知道这个标志实际上在做什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

空气里的味道 2024-07-21 16:22:06

请参阅关于此问题的我的文章

基本上,beforefieldinit 的意思是“可以在引用任何静态字段之前的任何时候初始化该类型”。 理论上,这意味着它可以非常延迟初始化 - 如果您调用不触及任何字段的静态方法,JIT 不需要初始化该类型。

实际上这意味着该类的初始化比其他情况要早 - 可以在第一个方法开始时对其进行初始化,可能< /em> 使用它。 将此与应用beforefieldinit的类型进行比较,其中类型初始化必须在第一次实际使用之前立即进行。

因此,假设我们有:

public static void DoSomething(bool which)
{
    if (which)
    {
        FirstType.Foo();
    }
    else
    {
        SecondType.Bar();
    }
}

如果两种类型都应用了 beforefieldinit (在 C# 中,除非该类型具有静态构造函数,否则它们默认这样做),那么它们将在 DoSomething 方法开始时初始化(通常 - 不能保证)。 如果它们没有 beforefieldinit,那么根据标志,只会初始化其中的一个

这就是为什么在实现单例模式<时通常使用静态构造函数(甚至是空的构造函数!) /a>.

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.

究竟谁懂我的在乎 2024-07-21 16:22:06

看起来它会在 4.6 中发生变化

https://github.com/dotnet/coreclr/issues /1193

Looks like it is going to change in 4.6

https://github.com/dotnet/coreclr/issues/1193

忘年祭陌 2024-07-21 16:22:06

引用自“CA1810:初始化引用类型静态字段内联(代码分析)- .NET | Microsoft Docs”,重点是我的,TL;DR 位于底部:

当类型声明显式静态构造函数时,即时 (JIT) 编译器会对该类型的每个静态方法和实例构造函数添加检查,以确保先前调用过静态构造函数。 当访问任何静态成员或创建该类型的实例时,会触发静态初始化。 但是,如果声明该类型的变量但不使用它,则不会触发静态初始化,如果初始化更改全局状态,这可能很重要。

当所有静态数据都内联初始化并且未声明显式静态构造函数时,Microsoft 中间语言 (MSIL) 编译器会添加 beforefieldinit 标志和隐式静态构造函数,该构造函数会初始化静态数据数据到 MSIL 类型定义。

当 JIT 编译器遇到 beforefieldinit 标志时,大多数情况下不会添加静态构造函数检查。 静态初始化保证在访问任何静态字段之前的某个时间发生,但不会在调用静态方法或实例构造函数之前发生。 请注意,静态初始化可以在声明该类型的变量后随时发生。

静态构造函数检查会降低性能。 通常,静态构造函数仅用于初始化静态字段,在这种情况下,您必须仅确保静态初始化发生在第一次访问静态字段之前。 beforefieldinit 行为适用于这些类型和大多数其他类型。 仅当静态初始化影响全局状态并且满足以下条件之一时,它才是不合适的:

  • 对全局状态的影响代价高昂,如果不使用该类型则不需要。

  • 无需访问该类型的任何静态字段即可访问全局状态效果。

TL;DR: beforefieldinit 标志有助于避免静态构造函数检查,这有助于提高性能(因为检查会影响性能)。 它通过告诉 JIT 在实际静态字段使用之前运行静态构造函数来实现此目的。

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.

你的心境我的脸 2024-07-21 16:22:06

如果标记为 BeforeFieldInit,则在首次访问为该类型定义的任何静态字段时或之前执行该类型的初始化方法。

如果未标记 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
first access to any static or instance field of that type, or
first invocation of any static, instance or virtual method of that type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文