2

インスタンスメソッド Object.Equals(Object) を検討しています。リフレクションを使用すると、次のように、このメソッドの IL をバイト配列として取得できます。

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

私は 2 台の PC を持っています。1 台は Windows XP を実行する 32 ビット マシンで、もう 1 台は Windows 7 を実行する 64 ビット マシンです。両方のマシンには、.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

4 番目のバイトが異なります。

これで、64 ビット プラットフォームでは mscorlib に 2 つの種類があることがわかりました。ただし、ILDASM は、このメソッドの IL がフレーバー間およびマシン間で同一であることを明らかにしています。x64 マシンでは、上記のコードを「任意の CPU」と「x86」の両方でターゲットにしましたが、結果は同じです。

私の質問は、この 2 台のマシンの間で指摘されている不一致を説明できる人はいますか?

アップデート

Object.Equals(Object) の C# と IL は次のとおりです。

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
4

2 に答える 2

10

メソッドを自分で作成し、ildasm.exe で確認するだけで、IL の内容をより深く理解できます。ildasm で View + Show bytes を使用して、バイト値を確認します。16 進数であることに注意してください。

.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 のバイトがメソッド tokenの一部であり、その最下位バイトであることがわかります。そして、私が得た値があなたが得たものとどのように大きく異なるかに注意してください. これは、テストするコードが非常に少ない非常に小さなプログラムを作成したためで、マニフェストが非常に小さいためです。逆アセンブラーは役に立ちます。トークン値を表示するだけでなく、実際にメタデータ テーブルでルックアップを行い、トークンをメソッド名に置き換えました。

トークンは、アセンブリ マニフェストのメタデータ テーブル内のインデックスです。このようなインデックスは、アセンブリ内のコードが変更され、テーブルへの追加が必要になると変更されます。詳細については、CLI 仕様のECMA 335を参照してください。

于 2013-02-19T13:16:44.527 に答える
1

異なるバイトは、を参照するメタデータ トークンRuntimeHelpers.Equals()の一部です。モジュールの再コンパイル時に、メタデータ トークンが安定しているとは限りません。そのため、他のアセンブリ内のシンボルへのバインドは、メタデータ トークンではなく名前で行われます。

于 2013-02-19T13:09:56.000 に答える