c# - C# Virtual 和 Override 的内部工作原理

标签 c# inheritance virtual overriding

关于 C# 虚拟和重写机制如何在内部工作的话题已经在程序员中讨论到死......但是在谷歌上半小时后,我找不到以下问题的答案(见下文):

使用简单的代码:

public class BaseClass
{
  public virtual SayNo() { return "NO!!!"; }
}

public class SecondClass: BaseClass
{
  public override SayNo() { return "No."; }
}

public class ThirdClass: SecondClass
{
  public override SayNo() { return "No..."; }
}

class Program
{
  static void Main()
  {
     ThirdClass thirdclass = new ThirdClass();
     string a = thirdclass.SayNo(); // this would return "No..."

     // Question: 
     // Is there a way, not using the "new" keyword and/or the "hide"
     // mechansim (i.e. not modifying the 3 classes above), can we somehow return
     // a string from the SecondClass or even the BaseClass only using the 
     // variable "third"?

     // I know the lines below won't get me to "NO!!!"
     BaseClass bc = (BaseClass)thirdclass;
     string b = bc.SayNo(); // this gives me "No..." but how to I get to "NO!!!"?
  }
}

我想我不能简单地使用最派生的实例(不修改 3 个类的方法签名)来获取基类或中间派生类的方法。但我想确认并巩固我的理解......

谢谢。

最佳答案

C# 无法做到这一点,但在 IL 中使用 call 而不是 callvirt 实际上可以。因此,您可以使用 Reflection.Emit 解决 C# 的限制。结合 DynamicMethod .

这里有一个非常简单的例子来说明它是如何工作的。如果您真的打算使用它,请将它包装在一个不错的函数中,努力使其适用于不同的委托(delegate)类型。

delegate string SayNoDelegate(BaseClass instance);

static void Main() {
    BaseClass target = new SecondClass();

    var method_args = new Type[] { typeof(BaseClass) };
    var pull = new DynamicMethod("pull", typeof(string), method_args);
    var method = typeof(BaseClass).GetMethod("SayNo", new Type[] {});
    var ilgen = pull.GetILGenerator();
    ilgen.Emit(OpCodes.Ldarg_0);
    ilgen.EmitCall(OpCodes.Call, method, null);
    ilgen.Emit(OpCodes.Ret);

    var call = (SayNoDelegate)pull.CreateDelegate(typeof(SayNoDelegate));
    Console.WriteLine("callvirt, in C#: {0}", target.SayNo());
    Console.WriteLine("call, in IL: {0}", call(target));
}

打印:

callvirt, in C#: No.
call, in IL: NO!!!

关于c# - C# Virtual 和 Override 的内部工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/751849/

相关文章:

c# - Web.config 转换不转换 VS 2017

C# Excel 文件 OLEDB 读取 HTML IMPORT

c++ - 是否可以在构造函数中使用模板方法模式?

c# - 为什么在 Entity Framework 模型定义中使用 'virtual' 作为类属性?

c# - 我如何安全地锁定此属性?

c# - 从实体的数字字段中选择最大数字 (Dynamics CRM 2016)

c++ - Objective-C++ 中的复杂类层次结构

c# - EF 6 数据库首先在生成的实体类中使所有属性虚拟化

java - 如果有很多类型,我不应该按对象类型进行子类化吗?

java - 如何避免警告 : return type requires unchecked conversion?