1

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)
{
    ....
} 

Resolverは、適切に選択した方法でアセンブリを作成できることを理解しました。私のアプリの場合、それは

Assembly.GetExecutingAssembly().GetManifestResourceStream(name);

ここで、 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].

プライベートインスタンス変数を削除しても、Fusionエラーは発生しません。

そのタイプの変数、または組み込みアセンブリで定義された他のタイプは、クラスのメンバーインスタンス変数として初期化されない限り、後で使用できます。インスタンスメソッドで型を使用できますが、問題ありません。


これを書いて、私は自分の質問に対する答えを思いついたのではないかと思っています。多分それはJITタイミングの問題です:多分インスタンスコンストラクターは静的コンストラクターが実行される前にJITされています。これは多分?フュージョンエラーにつながりますか?

誰かが何か洞察を持っていますか?

埋め込まれたアセンブリに依存するすべてのインスタンス変数を削除して、問題を回避するようにクラスを再設計できるため、これは大きな重大な問題ではありません。しかし、私はそれを理解したいと思います。

4

1 に答える 1

6

順序に関しては、あなたは正しいです。

静的コンストラクターが最初に実行され、次にパラメーター化されていないコンストラクター、次にパラメーター化されたコンストラクターが実行されます。

JITのタイミングは問題ではありません。CLRは、インスタンスが構築される前に静的コンストラクターが完了することを保証します。

ただし、静的コンストラクターが起動する前に、アセンブリの解決が行われています。ランタイムは、静的構造を呼び出す前に、アセンブリ(およびその依存関係)を解決する必要があります。そのため、この問題が発生しています。

于 2009-08-12T23:38:15.617 に答える