c# - `CallVirt` 和 `New` 关键字

标签 c# .net oop clr

这个问题链接到How CLR calls methods correctly hidden by derived class when reference is stored in a base class variable?

在我的例子中,我使用的是 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

Write方法的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。为什么调用 BaseClass.Methodcallvirt 是否在搜索方法时寻找特定的 override 标志?

最佳答案

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

你不妨问:“为什么这不调用 CompletelyDifferentName() ?”

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

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

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

答案是一样的:CompletelyDifferentName 与名为Methodvirtual(多态)方法没有任何关系。好吧,new void Method() 也不是 - 这就是 new 的意思

关于c# - `CallVirt` 和 `New` 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18226425/

相关文章:

c# - 如何为以编程方式添加到 View 中的控件实现事件?

.net - 制作 "hotkey"以在 WPF 中聚焦 TextBox

.net - Visual Studio 2008 : How to load source code while debugging

oop - 从数据库检索行的 search/get 方法应该是实例方法还是静态方法?

perl - Moo 的 MooseX::NonMoose 等价物是什么?

php - 为什么要为 doctrine2 类使用 getter setter

c# - 如何将8bit声音转换为16bit

c# - 委托(delegate)大会的主要流程是什么?

c# - 不同解决方案的两个项目之间的循环依赖

c# - 更新 net5.0 .csproj 到 net6.0