值
规则 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 删除。