2013-02-19 135 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()的一部分。当模块重新编译时,元数据令牌不保证稳定。这就是为什么绑定到其他程序集中的符号的原因是按名称而不是元数据标记。

相关问题