4

當我在C#4.0中嘗試使用新功能「可選參數」時,發現了這個有趣的事情。關於C#編譯器如何發出TypeRef信息的問題

我知道有使用在C#4.0「可選參數」兩種方式:

static void TestMethod(int parameter = 5) { } 
static void TestMethod2([Optional, DefaultParameterValue(5)]int parameter) { } 

現在,如果我編譯這段代碼,然後查看使用IL DASM組裝,然後我會看到,在IL DASM的「元信息」的窗口,有一個類型參考OptionalAttribute這樣的:

Token:    0x01000002 
ResolutionScope: 0x23000001 
TypeRefName:  System.Runtime.InteropServices.OptionalAttribute 
MemberRef #1 (0a000001) 
------------------------------------------------------- 
    Member: (0a000001) .ctor: 
    CallCnvntn: [DEFAULT] 
    hasThis 
    ReturnType: Void 
    No arguments. 

但沒有DefaultParameterValueAttribute的跡象。 這是爲什麼?

其實我認爲這兩個屬性都不應該在這裏,因爲編譯器對它們的處理方式不同,它們有自己的標誌值。爲了解釋我的意思,請看看這個:

Method #2 (06000002) 
------------------------------------------------------- 
    MethodName: TestMethod (06000002) 
    Flags  : [Private] [Static] [HideBySig] [ReuseSlot] (00000091) 
    RVA  : 0x00002053 
    ImplFlags : [IL] [Managed] (00000000) 
    CallCnvntn: [DEFAULT] 
    ReturnType: Void 
    1 Arguments 
     Argument #1: I4 
    1 Parameters 
     (1) ParamToken : (08000002) Name : parameter flags: [Optional] [HasDefault] (00001010) Default: (I4) 5 

Method #3 (06000003) 
------------------------------------------------------- 
    MethodName: TestMethod2 (06000003) 
    Flags  : [Private] [Static] [HideBySig] [ReuseSlot] (00000091) 
    RVA  : 0x00002056 
    ImplFlags : [IL] [Managed] (00000000) 
    CallCnvntn: [DEFAULT] 
    ReturnType: Void 
    1 Arguments 
     Argument #1: I4 
    1 Parameters 
     (1) ParamToken : (08000003) Name : parameter flags: [Optional] [HasDefault] (00001010) Default: (I4) 5 

這就是兩種方法的元數據。我們可以看到每個代碼段的最後一行已經存儲了默認參數值,那麼爲什麼仍然引用OptionalAttribute?

回答

3

這可以被視爲編譯器中的錯誤。如果仔細檢查程序集,則沒有任何內容引用OptionalAttribute TypeRef。

如果您沒有在TestMethod2中明確添加它,那麼TypeRef將不會出現在生成的程序集中。這只是簡單地表明該屬性是在第一遍中添加的,隨後被刪除。它還顯示編譯器對DefaultParameterValueAttribute的處理方式不同。

最終,這確實是一個小的實現細節,例如,Mono的C#編譯器不會在生成的程序集中爲任一屬性生成TypeRef。

+0

謝謝。這就是我所猜測的。向單聲道團隊敬禮:) – CuiPengFei 2011-04-13 06:55:34