gpt4 book ai didi

c# - 在其静态构造函数中创建类的实例 - 为什么允许这样做?

转载 作者:太空狗 更新时间:2023-10-29 21:07:05 25 4
gpt4 key购买 nike

关于 SO 的另一个问题激发了我在 C# 中尝试这段代码:

class Program
{
static Program()
{
new Program().Run();
}

static void Main(string[] args) { }

void Run()
{
System.Console.WriteLine("Running");
}
}

这会在运行时打印“Running”。

我实际上希望编译器会提示这个。毕竟,如果类还没有被静态构造函数初始化;我们如何确定对其调用方法是有效的?

那么为什么编译器不限制我们这样做呢?这有什么重要的使用场景吗?

编辑

我知道单例模式;问题在于为什么我可以在静态构造函数完成之前调用实例上的方法。到目前为止,JaredPar 的回答对此有一些很好的推理。

最佳答案

它是允许的,因为不允许它会更糟很多。像这样的代码会严重死锁:

class A {
public static readonly A a;
public static readonly B b;
static A() {
b = new B();
a = B.a;
}
}

class B {
public static readonly A a;
public static readonly B b;
static B() {
a = new A();
b = A.b;
}
}

你当然是在用装满子弹的枪指着你的脚。

此行为记录在 CLI 规范 (Ecma 335) 第 II 部分的第 10.5.3.2 章“宽松保证”中:

可以用属性 beforefieldinit(§10.1.6)标记类型,以指示不一定需要 §10.5.3.1 中指定的保证。特别地,不需要提供上面的最终要求:在调用或引用静态方法之前不需要执行类型初始化程序。

[基本原理:当代码可以在多个应用程序域中执行时,确保此最终保证变得特别昂贵。同时,对大量托管代码的检查表明很少需要这种最终保证,因为类型初始化器几乎总是用于初始化的简单方法静态字段。将其留给 CIL 生成器(因此可能留给程序员)来决定是否需要此保证,因此在需要时以一致性保证为代价提供效率。
结束理由]

C# 编译器确实会在类上发出 beforefieldinit 属性:

.class private auto ansi beforefieldinit ConsoleApplication2.Program
extends [mscorlib]System.Object
{
// etc...
}

关于c# - 在其静态构造函数中创建类的实例 - 为什么允许这样做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3630048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com