2013-02-19 136 views
2

我在考慮實例方法Object.Equals(Object)。使用反射,它是更多鈔票,以獲得IL此方法作爲一個字節數組,如下:爲什麼MethodBody.GetILAsByteArray在不同的平臺上返回不同的數組?

var mi = typeof(object).GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public); 
var mb = mi.GetMethodBody(); 
var bytes = mb.GetILAsByteArray(); 

我有兩個電腦:一個是運行Windows XP的32位機,另一種是64位的與Windows 7.這兩臺機器都安裝了.NET Framework 4.0.30319 SP1Rel。

在x86機器,結果數組是:

[0]: 2 
[1]: 3 
[2]: 40 
[3]: 122 
[4]: 67 
[5]: 0 
[6]: 6 
[7]: 42 

在x64的機器,不過,我得到這個:

[0]: 2 
[1]: 3 
[2]: 40 
[3]: 123 
[4]: 67 
[5]: 0 
[6]: 6 
[7]: 42 

第四個字節是不同的。

現在我知道mscorlib在64位平臺上有兩種口味。但是,ILDASM顯示,這種方法的IL在風味和機器之間是相同的。在x64機器上,我已經在「Any CPU」和「x86」上定位了上述代碼,但結果相同。

所以我的問題是,任何人都可以解釋兩臺機器之間的差異嗎?

UPDATE

這裏的C#和IL爲的Object.Equals(對象):

public virtual bool Equals(object obj) 
{ 
    return RuntimeHelpers.Equals(this, obj); 
} 

.maxstack 8 
IL_0000: ldarg.0 
IL_0001: ldarg.1 
IL_0002: call bool System.Runtime.CompilerServices.RuntimeHelpers::Equals(object, object) 
IL_0007: ret 
+0

也許你也可以向我們展示IL,所以我們可能有一些線索叫什麼方法。前三個字節是'ldarg.0''ldarg.1'和'call'。從第四個字節開始的值是目標。 – 2013-02-19 12:34:46

+0

我已經這樣做了。請參閱更新。 – 2013-02-19 12:51:43

回答

10

只需編寫自己的方法並用ildasm.exe查看,就可以更好地瞭解IL內容。使用搜索+顯示字節ILDASM看到字節值,注意,他們是在十六進制:

.method public hidebysig newslot virtual 
     instance bool Equals(object obj) cil managed 
// SIG: 20 01 02 1C 
{ 
    // Method begins at RVA 0x2052 
    // Code size  8 (0x8) 
    .maxstack 8 
    IL_0000: /* 02 |     */ ldarg.0 
    IL_0001: /* 03 |     */ ldarg.1 
    IL_0002: /* 28 | (0A)000010  */ call  bool [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::Equals(object, 
                                  object) 
    IL_0007: /* 2A |     */ ret 
} // end of method Program::Equals 

現在你會看到,在IL_0003字節是的方法令牌,最低顯著字節部分的。並注意我獲得的價值與獲得的價值有多大的不同。這是因爲我剛寫了一個非常小的程序,用很少的代碼來測試它,它有一個非常小的清單。反彙編器是有幫助的,而不是隻顯示它在元數據表中實際查找的令牌值,並用方法名稱替換令牌。

令牌是程序集清單的元數據表中的索引。當程序集中的代碼發生變化並且需要添加表格時,這樣的索引將會更改。您可以在CLI規範ECMA 335中閱讀有關它的更多信息。

+0

爲什麼你需要自己寫這個方法,而不是隻在mscorlib上指向ildasm? – svick 2013-02-19 13:19:23

+0

大概是爲我涉足一個我知道得太少的話題服務的權利。我天真地期望使用GetILAsByteArray作爲對象圖校驗和算法的基礎(其中圖的狀態和它的IL實現都被考慮在內)。我現在想我應該使用反彙編。 – 2013-02-19 14:07:47

+0

但是你正在看你自己的'Program.Equals',他正在從'mscorlib'看'Object.Equals'。由於他在兩個平臺上使用相同的版本,因此兩個mscorlib應該具有完全相同的清單,因此應該顯示完全相同的元數據標記值...對嗎?編輯:哦,等等,他不是在看同一版本。一個是32位的另一個64位。我的錯。 – Virtlink 2013-02-19 14:22:54

1

的不同字節是的metadatatoken參照RuntimeHelpers.Equals()的一部分。當模塊重新編譯時,元數據令牌不保證穩定。這就是爲什麼綁定到其他程序集中的符號的原因是按名稱而不是元數據標記。

相關問題