2009-08-12 69 views
0

假設我有一個帶有3個構造函數的類,一個默認(無參數)構造函數,一個參數化構造函數和一個靜態構造函數。像這樣:C#類的構造函數的順序:參數化,默認和靜態?

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

假設我調用參數化構造函數,這些構造函數按什麼順序執行?

我認爲這是靜態的,然後參數化,然後默認。但是......我的經歷並不同意這一點。背景:我有一個將引用的DLL作爲資源嵌入的應用程序。在運行時,應用程序註冊經由

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

一個組件解析器其中解析器方法這樣定義:

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

予理解的是,旋轉編碼器可以產生一個組件它織補以及選擇的任何方式。在我的應用程序的情況下,它確實

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

上面的'class'是什麼意思,在嵌入式程序集或加載類中是不是很明確?這可能很重要,因爲您可以使用靜態ctors進行排序和循環問題。 – 2009-08-14 11:26:04

+0

「該類」位於我正在編寫的代碼中,這將消耗外部程序集中的類型。我不知道在上面的問題中哪裏不清楚。如果我知道我可以編輯Q來澄清。 – Cheeso 2009-08-14 13:22:21

回答

5

你說得對,就訂單而言。

靜態構造函數先運行,然後運行非參數化構造函數,然後運行參數化構造函數。

JIT時間不應該是一個問題。 CLR保證您的靜態構造函數將在構造任何實例之前完成。

但是,在您的靜態構造函數觸發之前,組件解析正在發生。運行時需要在調用任何靜態構造之前解析程序集(及其依賴項)。這就是爲什麼你遇到這個問題。

+0

是的,我可以看到程序集在靜態構造函數觸發之前被引用。我認爲你完全正確。問題是,爲什麼是這種情況,*僅當實例變量使用嵌入式程序集中定義的類型時? – Cheeso 2009-08-13 01:29:38

+0

組件需要解析才能構造該類型。當你去訪問程序集中的類型時,它需要加載該程序集以及潛在的依賴程序集(它調用程序集解析),然後運行靜態初始化程序,然後運行靜態構造函數,然後運行實例構造函數。 – 2009-08-13 15:01:59

+0

是的,裏德 - 這是問題所在。這解釋了我所觀察到的。 – Cheeso 2009-08-13 17:26:38