CLRが参照型と多相をどのように実装しているかを理解しようとしています。私はDon BoxのEssential .Net Vol 1を参照しました。これは大部分のものを熱狂させる大きな助けとなります。しかし、私は、以下の問題で、私が立ち往生/混乱しています。callvirtはどのようにしてフードの下で動作しますか?
私は可能な限り問題を説明しようとします。 次のコード
class Base
{
public void m()
{
Console.WriteLine("Base.m");
}
}
class Derived : Base
{
public void m()
{
Console.WriteLine("Derived.m");
}
}
今すぐ、以下に示す主な方法のIL持つ単純なコンソールアプリケーションを検討し考えてみましょう。私は、オブジェクト参照として実行するために、このコードをNOTを期待していたILを理解するために、手動で、コンパイラによって作成され、ILAsm.exe
.class private auto ansi beforefieldinit Console1.Program
extends [mscorlib]System.Object
{
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 44 (0x2c)
.maxstack 1
.locals init ([0] class Console1.Base d)
nop
newobj instance void Console1.Base::.ctor()
stloc.0
ldloc.0
callvirt instance void Console1.Derived::m()
nop
call string [mscorlib]System.Console::ReadLine()
pop
ret
} // end of method Program::Main
} // end of class Console1.Program
再び組み立て微調整 は、ベースのオブジェクトを指すなし存在であります基本オブジェクトのメソッドテーブルには、Derivedクラスで定義されたメソッドm()のエントリがあります。
しかし、このコードは魔法のようにDerived.m()を実行します!!
だから、私は上記のコードでは理解していない二つの質問があります。
は、以下のILコードで指定されたタイプの意義は何ですか?私はこれを異なるタイプ(例えばSystem.Exception !!)に変更して試してみましたが、エラーは報告されていません。なぜ??作品をcallvirtどのように正確
.localsのinit([0]クラスConsole1.Base d)は
- ?コールはDerived.m()にどのようにルーティングされましたか?
ありがとうございます!
よろしく、 アジャイ
を@ulrichb:私は彼がそれをすることができるとは思わない。彼は実際に(例外を投げる)キャストを使用しない以外は、 'Base b = new Base();((派生)b).mのようなものです。 – CodesInChaos
コードは検証可能ですか? – CodesInChaos
@ CodeInChaos:コードは検証できません! PEVerifyは "予期しないタイプのスタック"エラーを返します。 – ajay