代码之家  ›  专栏  ›  技术社区  ›  Cheeso

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

  •  0
  • Cheeso  · 技术社区  · 15 年前

    假设我有一个类,有3个构造函数、一个默认(无参数)构造函数、一个参数化构造函数和一个静态构造函数。这样地:

    public MyClass()  { ... }
    public MyClass(string arg) : this()  { ...  }
    static MyClass()  { ... }
    

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

    我认为它是静态的,然后是参数化的,然后是默认的。但是…我的经验不同意这一点。


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

    static MyClass()
    {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
    }
    

    其中resolver方法的定义如下:

    static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
    {
        ....
    } 
    

    我知道分解器可以以它所能选择的任何方式产生一个组件。在我的应用程序中,它可以

    Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
    

    哪里 名称 是嵌入资源的名称。然后读取该资源的所有字节,并对所读取的字节块执行assembly.load(byte[])。

    一开始你可能觉得这很奇怪,但它起作用了。

    你可能会说, 为什么你要嵌入一个程序集,而不仅仅是ilmerge? 好问题。我认为我需要嵌入,因为嵌入的程序集已签名,并且我没有重新对合并的程序集签名的键。所以我嵌入了。

    问题是:假设我在类上声明了一个私有实例成员变量,该变量属于在嵌入程序集中定义的类型。在我的例子中,它是一个枚举,我还初始化了该枚举的值。

    现在,如果静态构造函数已经运行,那么该私有成员上的初始值设定项将不会有问题运行。但我看到的是一个“找不到文件”的错误——你的基本融合错误。

    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].
    

    如果我移除私有实例变量,那么就不会得到融合错误。

    我可以使用该类型的变量,或者嵌入程序集中定义的任何其他类型, 后来 ,只要它们没有初始化为类中的成员实例变量。我可以在实例方法中使用这些类型,没问题。


    把这个写下来,我想我可能已经想出了我自己问题的答案。可能这是一个JIT时间问题:可能实例构造函数在静态构造函数运行之前正在进行JIT。可能会这样?导致融合错误?

    有人有什么见解吗?

    这不是一个很大的关键问题,因为我可以重新设计类以避免这个问题,删除依赖于嵌入程序集的所有实例变量。但我想理解。

    1 回复  |  直到 15 年前
        1
  •  5
  •   Reed Copsey    15 年前

    你说得对,就顺序而言。

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

    JIT定时不应该是一个问题。clr保证静态构造函数将在构造任何实例之前完成。

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