前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CA1810:以内联方式初始化引用类型的静态字段

CA1810:以内联方式初始化引用类型的静态字段

作者头像
呆呆
发布2022-02-19 18:53:45
5970
发布2022-02-19 18:53:45
举报
文章被收录于专栏:centosDaicentosDai

规则 ID

CA1810

类别

“性能”

修复是中断修复还是非中断修复

非中断

原因

引用类型声明显式静态构造函数。

规则说明

当一个类型声明显式静态构造函数时,实时 (JIT) 编译器会向该类型的每个静态方法和实例构造函数中添加一项检查,以确保之前已调用该静态构造函数。 访问任何静态成员或创建该类型的实例时,将触发静态初始化。 但是,如果声明一个类型的变量,但不使用它,则不会触发静态初始化;这在初始化会更改全局状态的情况下非常重要。

当所有静态数据都以内联方式初始化并且未声明显式静态构造函数时,Microsoft 中间语言 (MSIL) 编译器会将 beforefieldinit 标志和隐式静态构造函数(该构造函数初始化静态数据)添加到 MSIL 类型定义。 JIT 编译器遇到 beforefieldinit 标志时,大多数情况下不会添加静态构造函数检查。 静态初始化可以保证在访问任何静态字段之前的某个时间发生,但不能在调用静态方法或实例构造函数之前发生。 请注意,在声明类型的变量后,可能会随时发生静态初始化。

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

影响全局状态的成本非常昂贵,如果不使用该类型,则不需要这样做。

可以在不访问该类型的任何静态字段的情况下访问全局状态效果。

如何解决冲突

要修复与该规则的冲突,请在声明它时初始化所有静态数据并移除静态构造函数。

何时禁止显示警告

如果不考虑性能,或者,如果静态初始化导致的全局状态更改成本非常昂贵,或者必须保证在调用该类型的静态方法或创建该类型的实例之前进行静态初始化,则可以安全地禁止显示此规则发出的警告。

示例

下面的示例演示了类型 StaticConstructor(该类型违反了规则)以及类型 NoStaticConstructor(该类型使用内联初始化替换静态构造函数来满足规则)。

public class StaticConstructor

{

static int someInteger;

static string resourceString;

static StaticConstructor()

{

someInteger = 3;

ResourceManager stringManager =

new ResourceManager("strings", Assembly.GetExecutingAssembly());

resourceString = stringManager.GetString("string");

}

}

public class NoStaticConstructor

{

static int someInteger = 3;

static string resourceString = InitializeResourceString();

static string InitializeResourceString()

{

ResourceManager stringManager =

new ResourceManager("strings", Assembly.GetExecutingAssembly());

return stringManager.GetString("string");

}

}

Imports System

Imports System.Resources

Namespace ca1810

Public Class StaticConstructor

Shared someInteger As Integer

Shared resourceString As String

Shared Sub New()

someInteger = 3

Dim stringManager As New ResourceManager("strings",

System.Reflection.Assembly.GetExecutingAssembly())

resourceString = stringManager.GetString("string")

End Sub

End Class

Public Class NoStaticConstructor

Shared someInteger As Integer = 3

Shared resourceString As String = InitializeResourceString()

Private Shared Function InitializeResourceString()

Dim stringManager As New ResourceManager("strings",

System.Reflection.Assembly.GetExecutingAssembly())

Return stringManager.GetString("string")

End Function

End Class

End Namespace

请注意在 NoStaticConstructor 类的 MSIL 定义上添加的 beforefieldinit 标志。

.class public auto ansi StaticConstructor

extends [mscorlib]System.Object

{

} // end of class StaticConstructor

.class public auto ansi beforefieldinit NoStaticConstructor

extends [mscorlib]System.Object

{

} // end of class NoStaticConstructor

相关规则

CA2207:以内联方式初始化值类型的静态字段

本文系外文翻译,前往查看

如有侵权,请联系?cloudcommunity@tencent.com?删除。

本文系外文翻译前往查看

如有侵权,请联系?cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com