在從相同的C#代碼(但可能不同的編譯器版本)生成的兩個程序集上運行ILDASM後,我從每個相應的dll獲得以下輸出。這些CIL語句有什麼區別?
.locals init (class MyClass/'<>c__DisplayClass3' V_0)
和
.locals init ([0] class MyClass/'<>c__DisplayClass3' 'CS$<>8__locals4')
是什麼這兩個語句之間的差異,具體是什麼'[0]'
符號的意義是什麼?
在從相同的C#代碼(但可能不同的編譯器版本)生成的兩個程序集上運行ILDASM後,我從每個相應的dll獲得以下輸出。這些CIL語句有什麼區別?
.locals init (class MyClass/'<>c__DisplayClass3' V_0)
和
.locals init ([0] class MyClass/'<>c__DisplayClass3' 'CS$<>8__locals4')
是什麼這兩個語句之間的差異,具體是什麼'[0]'
符號的意義是什麼?
這兩個語句在功能上是相同的。這種差異是由ILDASM在第二種情況下使用來自.pdb的數據引起的。當調試信息可用時,ILDASM包含變量名稱和索引;否則會給它們通用名稱並省略索引。
我只能推測索引是爲了幫助您將任何ldloc.x
指令與其變量名關聯起來。
順便說一句,明確提供可變折射率手工編輯MSIL時可能是有用的,因爲它會阻止你犯了一個錯誤添加或刪除當地人時:如果您稍後刪除x
沒有
.locals init ([0] int32 x,
[1] int32 y,
[2] int32 z)
ldloc.1 //load y
檢查你的方法並修復你的索引:
.locals init ([1] int32 y, //error -- Undefined type of local var slot 0 in method frob
[2] int32 z)
ldloc.1 //oops, would have loaded z
它被稱爲槽索引。該索引可用於引用適當的變量(與引用/按名稱訪問相同)。在第一個例子中,instanve將被V_0
名稱訪問,第二個由0
索引訪問。
[0]
- 插槽指數class MyClass/'<>c__DisplayClass3'
- 變量類型'CS$<>8__locals4'
- 變量名你有行代碼一起宣佈MyClass
類型的多個變量,你剛纔提到?
爲了澄清,IL是從包含在'MyClass'中的私有方法生成的。我相信'MyClass /'<> c__DisplayClass3''是爲方法中定義的lambda函數生成的類的名稱。我的主要興趣是爲什麼這個特定的陳述與可能不同的編譯器版本或操作系統環境有什麼不同,以及它是否有任何意義。感謝您的回答。 –
無論採用哪種方式,都需要使用'ldloc.0'將值壓入堆棧。我不確定爲什麼ildasm認爲它只有時才顯示索引是有用的。 – zinglon