4

オブジェクト参照が基本クラス変数に格納されているときに、オブジェクトが基本クラスメンバーを非表示にしたときに、CLRがメソッド呼び出しを正しくディスパッチする方法を理解しようとしています。

私の混乱のポイントは、実行時に作成されたオブジェクトヘッダーです。ヒープ上のオブジェクトヘッダーには、タイプポインターと同期ブロックインデックスの2つのフィールドがあります。タイプポインタは、クラスのメソッドテーブルを指します。オブジェクト参照が基本クラスであっても、ヒープ上に作成されたオブジェクトは派生クラスです。これにより、ランタイムは派生クラスオブジェクトのメソッドテーブルを使用するようになります。ただし、ランタイムは基本クラスのメンバーを正しく呼び出します。

このシナリオでCLRがメソッドを正しく呼び出す方法として、フローを理解するのを手伝っていただけませんか。

4

2 に答える 2

4

ここでは、オブジェクトヘッダーに記録されているオブジェクトタイプは重要ではありません。コンパイラーは、メソッドを呼び出す必要がある特定のクラスに名前を付けるメソッド呼び出しを発行します。生成されたILでかなり目に見えます。例えば:

class Base {
    void foo() { }
    void callFoo() {
        foo();         // <== here
    }
}
class Derived : Base {
    new void foo() { }
}

示されたステートメントは、このILを生成します。

IL_0002:  call       instance void ConsoleApplication1.Base::foo()

呼び出しオペコードにBaseが存在することに注意してください。あいまいさはありません。

于 2012-08-18T10:06:34.523 に答える
1

仮想化されていない、またはオーバーライドされていないメソッドを呼び出すことは、メソッドテーブルとは何の関係もありません。C#コンパイラはそのメソッドを名前で呼び出し(アセンブリには実際には文字列として名前が含まれています!)、JITは関数のアドレスを出力されたx86コードにハードコードします。thisアドレスは、オブジェクト参照の実行時タイプに依存しません。

于 2012-08-18T10:09:35.593 に答える