C#用Call代替CallVirt之后的测试用例

一. C# 原始代码和直接结果

测试 C# 代码:

class Program
{
    static void Main(string[] args)
    {
        A c1 = new C();
        c1.Foo();

        C c2 = new C();
        c2.Foo();

        Console.ReadKey();
    }
}
class A
{
    public virtual void Foo()
    {
        Console.WriteLine("Call on A.Foo()");
    }
}
class B : A
{
    public override void Foo()
    {
        Console.WriteLine("Call on B.Foo()");
    }
}
class C : B
{
    public new void Foo()
    {
        Console.WriteLine("Call on C.Foo()");
    }
}

运行结果:

二. IL程序编译的IL代码执行结果

IL 代码:

.assembly extern mscorlib
{
    auto
}
.assembly MyTest{}
.module MyTest.exe

.class public A
{
    .method public specialname void .ctor()
    {
        ldarg.0
        call instance void [mscorlib]System.Object::.ctor()
        ret
    }
    
    .method public newslot virtual void Foo()
    {
        ldstr "Call on A.Foo()"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}
.class public B extends A
{
    .method public specialname void .ctor()
    {
        ldarg.0
        call instance void A::.ctor()
        ret
    }
    
    .method public virtual void Foo()
    {
        ldstr "Call on B.Foo()"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}
.class public C extends B
{
    .method public specialname void .ctor()
    {
        ldarg.0
        call instance void B::.ctor()
        ret
    }
    
    .method public void Foo()
    {
        ldstr "Call on C.Foo()"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}
.method public static void Main()
{
    .entrypoint
    .locals (class A v_0,class C v_1)
    newobj instance void C::.ctor()
    stloc.0
    ldloc.0
    callvirt instance void A::Foo()
    newobj instance void C::.ctor()
    stloc.1
    ldloc.1
    callvirt instance void C::Foo()
    call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    pop
    ret
}

运行结果:

 三. 用 Call 代替 CallVirt 的 IL

IL 代码:

.assembly extern mscorlib
{
    auto
}
.assembly MyTest{}
.module MyTest.exe

.class public A
{
    .method public specialname void .ctor()
    {
        ldarg.0
        call instance void [mscorlib]System.Object::.ctor()
        ret
    }
    
    .method public newslot virtual void Foo()
    {
        ldstr "Call on A.Foo()"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}
.class public B extends A
{
    .method public specialname void .ctor()
    {
        ldarg.0
        call instance void A::.ctor()
        ret
    }
    
    .method public virtual void Foo()
    {
        ldstr "Call on B.Foo()"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}
.class public C extends B
{
    .method public specialname void .ctor()
    {
        ldarg.0
        call instance void B::.ctor()
        ret
    }
    
    .method public void Foo()
    {
        ldstr "Call on C.Foo()"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }
}
.method public static void Main()
{
    .entrypoint
    .locals (class A v_0,class C v_1)
    newobj instance void C::.ctor()
    stloc.0
    ldloc.0
    call instance void A::Foo()
    newobj instance void C::.ctor()
    stloc.1
    ldloc.1
    call instance void C::Foo()
    call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    pop
    ret
}

运行结果:

四. 结论

如果使用 Call 的话,它会简单粗暴的指针调用代码,即 A 中的 Foo 方法的代码进行执行。

posted @ 2019-11-28 18:44  霁雪湖上三映月  阅读(394)  评论(0编辑  收藏  举报