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

2023-11-21

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 个类的方法签名)。但我想确认并巩固我的理解......

Thanks.


C# 做不到这一点,但它is实际上可以在 IL 中使用call代替callvirt。因此,您可以通过使用来解决 C# 的限制Reflection.Emit结合一个DynamicMethod.

这是一个非常简单的示例来说明其工作原理。如果您确实打算使用它,请将其包装在一个很好的函数中,努力使其能够与不同的委托类型一起使用。

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));
}

Prints:

callvirt, in C#: No.
call, in IL: NO!!!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# Virtual 和 Override 的内部工作原理 的相关文章

随机推荐

  • C++ 复制构造函数签名:重要吗

    我当前的实现使用大量具有此语法的复制构造函数 MyClass Myclass Myclass my class 它真的 功能上 不同于 MyClass MyClass const MyClass my class and why 有人建议我
  • 在 WinRT 应用程序中处理两根、三根、四根手指滑动手势

    我有以下代码 private Point initialpoint private void ManipulationStarted object sender ManipulationStartedRoutedEventArgs e in
  • java中的继承继承变量?

    据我了解继承的类也应该继承变量 那么为什么这段代码不起作用呢 public class a private int num public static void main String args b d new b class b exte
  • 为什么我的控件不接受键盘输入?

    我已经构建了一个自定义控件 我正在尝试向其发送输入 它将接受鼠标输入并正确报告 MouseDown MouseMove 和 MouseUp 但无论出于何种原因 它都不会接受键盘输入 当我单击它时 它不会获得焦点 并且我按下的任何键都会被已经
  • 动态更新ViewPager?

    我无法更新 ViewPager 中的内容 FragmentPagerAdapter 类中 instantiateItem 和 getItem 方法的正确用法是什么 我仅使用 getItem 来实例化并返回我的片段 Override publ
  • Cordova 3.1.0:找不到插件或不是 CDVPlugin

    我正在尝试构建我的第一个 Cordova 应用程序 但无法使用插件 我的应用程序是使用 Cordova 命令行界面构建的 因此我以这种方式添加了相机插件 cordova plugin add https git wip us apache
  • 无法在 WorkManager 中设置自定义工作工厂

    我使用此代码来设置我自己的工人工厂 val daggerWorkerFactory DaggerWorkerFactory toInjectInWorker val configuration Configuration Builder s
  • 如何通过 3d 到 2d 点对应估计相机位姿(使用 opencv)

    你好 我的目标是发展用于飞机 模拟器 驾驶舱的头部跟踪功能 以提供AR支持民用飞行员在视觉条件较差的情况下着陆和飞行 我的方法是检测我知道其 3D 坐标的特征点 在黑暗模拟器 LED 中 然后计算估计的 头戴式相机的 姿势 R t 旋转与平
  • 如何在 Matlab 中从 3D 矩阵制作视频

    我在 matlab 中有一大堆 2D 矩阵 它们应该组成一个 3D 矩阵 其中第三维是时间 我正在尝试从图像数据制作视频 我知道我可以使用 surf 使用二维矩阵之一制作曲面图 但我不确定要调用哪个命令来获取所有二维矩阵并将它们转换为曲面图
  • 带有自定义 ListView 的 DialogFragment

    我正在尝试创建一个 DialogFragment 它显示一个带有自定义 ListView 的对话框 public class MultiSelectDialogCustom extends DialogFragment ListView m
  • 如何使用流减少保留所有列表列表

    我面临以下问题 我有一个列表列表 我只想保留所有列表 我正在尝试处理流 private List
  • 如何在每次单击按钮时旋转 imageview 中的图像?

    这是java代码 我从图片库获取图像 我有一个按钮和一个ImageView 它只旋转一次 当我再次单击按钮时 它不会旋转图像 public class EditActivity extends ActionBarActivity priva
  • 为什么我无法使用 AT 命令接收短信?

    我想使用 AT 命令从我的电脑向我的手机发送 接收短信 我使用 USB 端口将手机连接到电脑 我的计算机检测到调制解调器 并且我能够从计算机向手机发送短信 但是我的电脑收不到短信 我正在展示我从 AT 编辑器获得的示例 AT CMGF 1
  • 如何在Xaml中单击时更改按钮内容?

    我有名为 保持按钮 的按钮内容 一旦我单击按钮 按钮内容应更改为 恢复 再次如果按下 恢复 按钮 则意味着 保持 应可见 XAML 代码
  • Intent 和 setContentView 之间的区别

    在我的主要活动中 加载视图作为意图或使用 setContentView 之间有区别吗 public class MainActivity extends Activity Override public void onCreate Bund
  • 理解 matplotlib 顶点

    我正在尝试在 matplotlib 中为散点图创建自定义标记 其中标记是具有固定高度和变化宽度的矩形 每个标记的宽度是 y 值的函数 我尝试过这样使用这段代码作为模板并假设如果给定 verts 一个 N 二维元组的列表 它会绘制具有相应第一
  • TSQL:如何将本地时间转换为UTC? (SQL Server 2008)

    我们正在处理一个需要处理来自不同时区和夏令时设置的全球时间数据的应用程序 这个想法是在内部以 UTC 格式存储所有内容 并且仅针对本地化用户界面来回转换 SQL Server 是否提供任何机制来处理给定时间 国家 地区和时区的翻译 这一定是
  • 杰克逊未填充所有属性

    我正在研究一个简单的例子Jackson library转换一个json串回Java object但我看到我的 java 对象上只设置了很少的属性 而不是所有属性 这是我的代码 import java io BufferedReader im
  • Linux 上的 C 异步、定时函数调用?

    Linux 上的 C 语言在一定延迟后异步调用函数的最简单 最有效的方法是什么 如 JavaScript 的setTimeout 或设置一个重复计时器定期调用它 类似于setInterval 虽然这个问题适用于Linux 但我希望有一种跨平
  • C# Virtual 和 Override 的内部工作原理

    C 虚拟和重写机制如何在内部工作的话题已经在程序员中讨论得死去活来了 但是在谷歌上半小时后 我找不到以下问题的答案 见下文 使用简单的代码 public class BaseClass public virtual SayNo return