C#类的构造函数顺序:参数化,默认和静态?

Che*_*eso 0 .net constructor class-design fusion

假设我有一个包含3个构造函数的类,一个默认(无参数)构造函数,一个参数化构造函数和一个静态构造函数.像这样:

public MyClass()  { ... }
public MyClass(string arg) : this()  { ...  }
static MyClass()  { ... }
Run Code Online (Sandbox Code Playgroud)

假设我调用参数化构造函数,这些构造函数以什么顺序执行?

我认为它是静态的,然后参数化,然后默认.但是......我的经历并不同意.


背景:我有一个应用程序嵌入引用的DLL作为资源.在运行时,应用程序通过注册程序集解析程序

static MyClass()
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
}
Run Code Online (Sandbox Code Playgroud)

Resolver方法定义如下:

static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
    ....
} 
Run Code Online (Sandbox Code Playgroud)

我知道解析器可以按照它选择的任何方式生成装配.在我的应用程序的情况下,它做了一个

Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
Run Code Online (Sandbox Code Playgroud)

其中name是嵌入资源的名称.然后读取该资源的所有字节,并对读取的字节块执行Assembly.Load(byte []).

起初,这可能听起来很奇怪,但它确实有效.

你可能会说,为什么世界上你会嵌入一个集会,而不仅仅是ILMerge? 好问题.我认为我需要嵌入因为嵌入式程序集已签名,而且我没有重新签署合并程序集的密钥.所以我嵌入了.

问题是:假设我在类上声明了一个私有实例成员变量,该变量是嵌入式程序集中定义的类型.在我的情况下,它是一个枚举,我也初始化该枚举的值.

现在,如果静态构造函数已经运行,那么该私有成员上的初始化程序将没有问题.但我看到的是"找不到文件"错误 - 您的基本Fusion错误.

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'MyApp, Version=1.1.4.1, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c' or one of its dependencies. The system cannot find the file specified.
File name: 'MyApp, Version=1.1.4.1, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c'

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value[HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
Run Code Online (Sandbox Code Playgroud)

如果我删除私​​有实例变量,那么我没有得到Fusion错误.

我可以使用该类型,或在嵌入式组件限定,任何其它类型的变量,只要它们不作为在类成员的实例变量初始化上.我可以在实例方法中使用类型,没问题.


写这篇文章,我想我可能已经想出了我自己的问题的答案.也许这是一个JIT计时问题:在静态构造函数运行之前,实例构造函数可能正在进行JIT.也许吧?导致Fusion错误?

谁有任何见解?

这不是一个非常重要的问题,因为我可以重新设计类来避免这个问题,删除所有依赖于嵌入式程序集的实例变量.但我想了解它.

Ree*_*sey 5

就订单而言,你是对的.

首先运行静态构造函数,然后运行非参数化构造函数,然后运行参数化构造函数.

JIT时间不应成为问题.CLR保证在构造任何实例之前完成静态构造函数.

但是,在静态构造函数触发之前,会发生程序集解析.运行时需要在调用任何静态构造之前解析程序集(及其依赖项).这就是你遇到这个问题的原因.