C# `CallVirt`和`New`关键字

C# `CallVirt`和`New`关键字,c#,.net,oop,clr,C#,.net,Oop,Clr,这个问题与 在我的例子中,我使用的是callvirt指令,而不是call class BaseClass { public void Write() { Method(); } protected virtual void Method() { Console.WriteLine("Base - Method"); } }

这个问题与

在我的例子中,我使用的是
callvirt
指令,而不是
call

     class BaseClass
    {
        public void Write()
        {
            Method();
        }

        protected virtual void Method()
        {
            Console.WriteLine("Base - Method");
        }
    }

    class DerivedClass : BaseClass
    {
        private new void Method()
        {
            Console.WriteLine("Derived - Method");
        }
    }

    static void Main(string[] args)
    {
        DerivedClass dc = new DerivedClass();
        BaseClass bcdc = new DerivedClass();

        dc.Write();
        bcdc.Write();

        Console.ReadKey(true);
    }
输出:

 Base - Method
 Base - Method
写入方法的IL代码:

   .method public hidebysig instance void  Write() cil managed
   {
      // Code size       9 (0x9)
     .maxstack  8
     IL_0000:  nop
     IL_0001:  ldarg.0
     IL_0002:  callvirt   instance void Private_override.Program/BaseClass::Method()
     IL_0007:  nop
     IL_0008:  ret
   } // end of method BaseClass::Write
我不明白为什么要调用
Base
方法


在这里,CLR使用
callvirt
指令,这意味着它将查找调用变量类型,因为类型是
DerivedClass
DerivedClass
隐藏
BaseClass.Method
,所以堆中DerivedClass的MethodTable中应该只有
DerivedClass.Method
。为什么调用基类方法
?当搜索方法时,
callvirt
是否查找特定的
override
标志

因为你没有覆盖它。将
new
更改为
override
,它将按照您讨论的方式运行(您还必须将可访问性更改为
protected
,否则它将无法编译)
new
创建一个恰好共享名称的不相关的方法-它不是基类中同名的其他方法的多态树的一部分

您可能会问:“为什么这个调用不完全区分名称()
?”


答案是一样的:
完全不同的名称
与名为
方法
虚拟
(多态)方法没有任何关系。嗯,
new void Method()
-这就是
new
在这里的意思。

因为这正是new应该如何工作的。 New意味着您的新方法与基类中同名的方法没有任何共同之处。 这与使用另一个名称在派生类方法中创建相同,只是使用了相同的名称。
也就是说,基类方法write不会尝试调用新方法,因为它不是基类中方法的新版本,它只是该类的另一个成员。

我标记了
DerivedClass.method
以覆盖基类方法。在IL中,我看到
.methodfamily隐藏虚拟实例void method()cil managed
。这是否意味着
callvirt
在查找派生方法时实际搜索
virtual
关键字?使用
new
关键字IL是
.method private hidebysig instance void method()cil managed
——这是一个普通的方法。@nikita:正如所有其他人所说,“new”创建了一个不相关的方法,恰好具有相同的名称,与“override”相反。因此,请看:
private new void Method()
。这种方法是正常的。它不是虚拟的,只是
私有void Method()
,因此编译器发出了一个普通方法。如果您编写了
private new virtual void Method()
,那么它将创建一个虚拟方法。新的、虚拟的、与基础虚拟无关的。请注意,当您重写时,创建的方法显然是自动虚拟的。但是,新技术并不意味着任何形式的“虚拟”。
class BaseClass
{
    public void Write()
    {
        Method();
    }

    protected virtual void Method()
    {
        Console.WriteLine("Base - Method");
    }
}

class DerivedClass : BaseClass
{
    private void CompletelyDifferentName()
    {
        Console.WriteLine("Derived - Method");
    }
}