.net 为什么MethodBody.GetILAsByteArray在不同平台上返回不同的数组?

.net 为什么MethodBody.GetILAsByteArray在不同平台上返回不同的数组?,.net,reflection,cil,il,mscorlib,.net,Reflection,Cil,Il,Mscorlib,我正在考虑实例方法Object.Equals(Object)。使用反射,可以将此方法的IL作为字节数组获取,如下所示: var mi = typeof(object).GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public); var mb = mi.GetMethodBody(); var bytes = mb.GetILAsByteArray(); 我有两台电脑:一台是运行WindowsXP的32位电脑,另一台是64位

我正在考虑实例方法Object.Equals(Object)。使用反射,可以将此方法的IL作为字节数组获取,如下所示:

var mi = typeof(object).GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public);
var mb = mi.GetMethodBody();
var bytes = mb.GetILAsByteArray();
我有两台电脑:一台是运行WindowsXP的32位电脑,另一台是64位的Windows7电脑。这两台机器都安装了.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机器上,我将上述代码的目标同时指向“任意CPU”和“x86”,但结果是相同的

所以我的问题是,有人能解释这两台机器之间的差异吗

更新

这是Object.Equals(Object)的C#和IL:


不同的字节是引用
RuntimeHelpers.Equals()
的部分。在重新编译模块时,元数据标记不能保证稳定。这就是为什么绑定到其他程序集中的符号是按名称而不是按元数据标记进行的。

只需自己编写方法并使用ildasm.exe查看它,就可以更好地了解IL内容。使用ildasm中的View+Show bytes查看字节值,注意它们是十六进制的:

.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规范中阅读更多关于它的信息。

也许您也可以向我们展示IL,这样我们就可以知道在那里调用了什么方法了。前三个字节是
ldarg.0
ldarg.1
call
。从第四个字节开始的值就是目标。我已经这样做了。请看更新。为什么你需要自己编写这个方法,而不仅仅是将ildasm指向mscorlib?也许我涉足一个我知道得太少的主题是对的。我天真地希望使用GetILAsByteArray作为对象图校验和算法的基础(在该算法中,图的状态及其IL实现都被考虑在内)。我现在想我应该使用反汇编程序。但是你在看你自己的
程序。Equals
,他在看
对象。Equals
来自
mscorlib
。因为他在两个平台上使用相同的版本,所以两个mscorlib应该具有完全相同的清单,因此应该显示完全相同的元数据令牌值。。。正确的?编辑:哦,等等,他看的不是同一个版本。一个是32位,另一个是64位。我的错。除了在我的64位机器上加载32位版本的mscorlib时,我认为我看到的是相同的版本。
.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