C# 静态参数的初始化顺序
几周前,我从Java转到了C。今天,我有一个奇怪的行为,我试图在这个简单的样本中重现它。我用的是.NETFW4 我有三门课: 首先,抽象的一点:C# 静态参数的初始化顺序,c#,.net,compiler-construction,initialization,C#,.net,Compiler Construction,Initialization,几周前,我从Java转到了C。今天,我有一个奇怪的行为,我试图在这个简单的样本中重现它。我用的是.NETFW4 我有三门课: 首先,抽象的一点: namespace ReadonlyStaticOrder { using System; using System.Collections.Generic; public abstract class AbstractClass { public AbstractClass(string value,
namespace ReadonlyStaticOrder
{
using System;
using System.Collections.Generic;
public abstract class AbstractClass
{
public AbstractClass(string value, IEnumerable<string> someValues)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (someValues == null)
{
throw new ArgumentNullException("someValues");
}
// would do something after...
}
}
}
输出为:
的类型初始值设定项
“ReadonlyStaticOrder.ReadonlyOrderInitialization”引发异常。
值不能为null。参数名称:someValues at
ReadOnlyStatiOrder.ReadonlyOrderInitialization..ctor(字符串值)在中的ReadOnlyStatiOrder.Program.Main(字符串[]args)处 d:\stackoverflow\static ReadOnlySue\ConsoleApplication1\ReadonlyStaticOrder\Program.cs:line 十二, 我在介绍bug的那一行添加了一条注释。对我来说,编译器必须警告我,由于静态初始化的顺序,这种行为可能会很奇怪。我错了吗
谢谢大家,我希望你们有足够的信息。通常,如果您试图在初始化成员之前使用它们,编译器会发出警告 在这种情况下,您可以绕过此检查,因为静态成员不直接使用另一个静态成员,而是调用使用另一个静态成员的构造函数 编译器不能保护您免受所有可能的依赖性问题的影响,只有那些简单的问题。对于编译器来说,这只是一个过于复杂的步骤
当然,编译器可以捕获类似的内容,但这会使每一个附加的依赖级别都变得更加复杂,并且仍然不可能捕获所有情况。它被定义为ECMA 334中的文本顺序-§17.11: 如果一个类包含任何带有初始值设定项的静态字段,则这些初始值设定项将在执行静态构造函数之前以文本顺序执行 顺便说一下,如果您考虑
为什么,;考虑(注:这些只是我自己的想法):
- “确定赋值”通常会阻止这一问题,但“确定赋值”不适用于字段
- 全面详细地分析代码在计算上是复杂的(我认为可能是“暂停”),因此它只能提供一个不完整的安全外表(这是人为的,在任何非平凡的场景中都可能导致问题)
- 由于
问题,完整订单本身没有严格定义;因此,它不能处理一般情况,而且,覆盖特定情况(单个类片段等)又回到了“薄薄的表面”(它只对明显的情况发出警告,而对非琐碎的情况则无能为力)部分类
gmcs
)测试了一个简单的示例-没有警告,并且严格按照文本顺序:
namespace ReadonlyStaticOrder
{
using System.Collections.Generic;
public sealed class ReadonlyOrderInitialization : AbstractClass
{
// this line introduces the bug, since it call the ctor before SomeValues already initialized
// if removed, no more exception
public static readonly ReadonlyOrderInitialization Sample = new ReadonlyOrderInitialization("sample");
private static readonly IEnumerable<string> SomeValues = new string[] { "one", "two", "three" };
public ReadonlyOrderInitialization(string value)
: base(value, SomeValues)
{
}
}
}
namespace ReadonlyStaticOrder
{
using System;
public sealed class Program
{
static void Main(string[] args)
{
try
{
new ReadonlyOrderInitialization("test");
}
catch (TypeInitializationException typeInitializationException)
{
Console.WriteLine(typeInitializationException.Message);
Console.WriteLine(typeInitializationException.InnerException.Message);
Console.WriteLine(typeInitializationException.StackTrace);
}
Console.ReadLine();
}
}
}