2009-08-12 20 views
0

3つのコンストラクタ、デフォルト(引数なし)コンストラクタ、パラメータ化されたコンストラクタ、および静的コンストラクタを持つクラスがあるとします。C#クラスのコンストラクタの順序:パラメータ化、デフォルト、および静的?

これらのコンストラクタはどのような順序で実行されますか?

私はそれが静的だったと思って、次にパラメータ化されてからデフォルトになったと思っていました。しかし、...私の経験はそれに同意していません。


背景:リソースとして参照されたDLLを埋め込んだアプリケーションがあります。 Iレゾルバアセンブリにそれがとてもよく選ぶ任意の方法を作り出すことができることを理解

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

:実行時に、アプリケーションは

static MyClass() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver); 
} 
リゾルバ方法は次のように定義され

介しアセンブリリゾルバを登録します。私のアプリの場合は、名前が埋め込まれたリソースの名前です

Assembly.GetExecutingAssembly().GetManifestResourceStream(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されている可能性があります。これは多分でしょうか? Fusionエラーにつながりますか?

誰でも洞察力がありますか?

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

+0

上記の 'the class'の意味はあまり明確ではありません。組み込みアセンブリやローディングクラスにありますか?あなたが静的なctorsで順序と循環の問題を持つことができるので重要です。 –

+0

"クラス"は私が書いているコードにあり、外部アセンブリの型を消費します。上記の質問ではどこが不明かわかりません。私が知っていれば、Qを編集して明確にすることができました。 – Cheeso

答えて

5

あなたは正しいと言えます。

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

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

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

+0

はい、静的コンストラクタが起動する前にアセンブリが参照されていることがわかります。私はあなたが正しいと思います。問題は、インスタンス変数が組み込みアセンブリで定義された型を使用する場合のみです。 – Cheeso

+0

型を構築するためにアセンブリを解決する必要があります。アセンブリ内の型にアクセスするには、そのアセンブリ、および潜在的に依存するアセンブリ(アセンブリ解決を呼び出す)をロードする必要があります。次に、静的イニシャライザを実行した後、その型で静的コンストラクタを実行し、次にインスタンスコンストラクタを実行します。 –

+0

はい、リード - それが問題です。それは私が何を観察したかを説明する – Cheeso

関連する問題