先上测试代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace TestVirt
{
class Program
{
static void Main(string[] args)
{
A c1 = new C();
c1.Foo(); C c2 = new C();
c2.Foo(); Console.ReadLine();
}
} 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()");
}
}
}

可能你对C c2 = new C();这个的结果没有什么疑问,但是对A c1 = new C();的结果百思不解。呵呵,我们慢慢来看这个区别,先来看看最终的IL代码是什么样子的:

.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// 代码大小 34 (0x22)
.maxstack 1
.locals init ([0] class TestVirt.A c1,
[1] class TestVirt.C c2)
IL_0000: nop
IL_0001: newobj instance void TestVirt.C::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance void TestVirt.A::Foo()
IL_000d: nop
IL_000e: newobj instance void TestVirt.C::.ctor()
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: callvirt instance void TestVirt.C::Foo()
IL_001a: nop
IL_001b: call string [mscorlib]System.Console::ReadLine()
IL_0020: pop
IL_0021: ret
} // end of method Program::Main

  

根据IL的结果,我们明显可以看到,两次调用不同的地方就在于一个是Call的A的Foo,一个是C的Foo。

但是这里你注意了:我们new的是同样的一个对象,他们具有同样的内存布局。

用WinDbg来看看我们new出来对象的MethodTable是长什么样子的吧:

看到没有,这个C对象的方法表里面同时包括了C自己定义的Foo和上一层次父对象的Foo方法。

结合IL的结果和C对象的方法表的Dump结果,相信看官已经明白为啥两次调用为啥会用不同了吧。

算了,还是简单描述一下吧:首先根据il的结果明显两次调用请求的方法是不同的;其次,你可以看到我们的C对象引用的方法表里面确实有两个Foo方法。

呵呵,这样同样类型的对象对不同方法调用的请求是不是就可以分开了呢?当然是!

PS:可能会有人问:为啥我请求的A.Foo()你这个MethodTable里面没有呢?

脑补下吧哥:被B给override了。

结合IL和Windbg来看.Net调用继承虚方法的执行顺序的更多相关文章

  1. Odoo(OpenERP) 多个子类重载同一个父类方法的执行顺序及如何调用父类的父类方法

    首先说下起因,在修改英国会计模块(没错,就是那个安格鲁撒克逊记账模式!)中不符合中国国情的部分供能时,碰到了一个棘手的问题,简单的说就是B类继承它的父类A并重载了A的方法M,同时C类也继承了A类也重载 ...

  2. 实现继承+接口继承+虚方法+隐藏方法+this/base+抽象类+密封类/方法+修饰符

    概念: 在上一节课中学习了如何定义类,用类当做模板来声明我们的数据. 很多类中有相似的数据,比如在一个游戏中,有Boss类,小怪类Enemy,这些类他们有很多相同的属性,也有不同的,这个时候我们可以使 ...

  3. odoo开发笔记 -- 多个子类继承同一个父类方法的执行顺序

    场景描述: odoo模块化开发的架构理念,科学&高效, 可以让很多业务场景,尽可能松耦合:让开发人员的主要精力,关注在当前的业务逻辑: 所谓「前人栽树,后人乘凉」,模块整体好比一棵大树, 开发 ...

  4. Java基础-继承-子类与父类执行顺序

    代码 public class Test { public static void main(String[] args) { new Circle(); } } class Draw { publi ...

  5. Java 继承中构造方法的执行顺序问题

    在Java中,如果一个类没有任何显式创建的构造器则该类默认会有一个无参构造器:如果显式创建了有参构造器则该类就不再有默认无参构造器. 在Java继承中,构造器并不能被继承,而是被显示或隐式调用. 1. ...

  6. java中子类继承父类程序执行顺序问题

    Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分,它们的执行顺序相对来说比较简单,用程序也很容易验证.比如新建一个测试父类. public ...

  7. super方法 调用父类的方法

    描述 super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重复 ...

  8. Java 基础:继承中的执行顺序

    1.单独的父类测试 Java中,new一个类的对象,类里面的静态代码块.非静态代码.无参构造方法.有参构造方法.类的一般方法等部分, 它们的执行顺序相对来说比较简单,用程序也很容易验证. 比如新建一个 ...

  9. java中子类继承父类程序执行顺序

    java中子类继承父类程序执行顺序 FatherTest.java public class FatherTest { private String name; public FatherTest() ...

随机推荐

  1. Xgboost的sklearn接口参数说明

    from xgboost.sklearn import XGBClassifier model=XGBClassifier(base_score=0.5, booster='gbtree', cols ...

  2. [poj 2106] Boolean Expressions 递归

    Description The objective of the program you are going to produce is to evaluate boolean expressions ...

  3. vue使用过程常见的一些问题

    Vue目前的的开发模式主要有两种:1.直接页面级的开发,script直接引入Vue2.工程性开发,webpack+loader或者直接使用脚手架工具Vue-cli,里面的文件都配置好了 webpack ...

  4. ios swift 实现简单MVP模式

    在移动开发中,会用到各种架构,比如mvp,mvvm等,其目的就是为了让项目代码的可读性更好,减轻在android(activity) ios(controller)中的大量代码问题.接下来就开始我们的 ...

  5. (转)Jmeter参数化

    设置参数值的方法有如下几种: 1. 用Jmeter中的函数获取参数值,__Random,__threadNum,__CSVRead,__StringFromFile,具体调用方法如下:${__Rand ...

  6. 3、OpenCV Python 色彩空间

    __author__ = "WSX" import cv2 as cv import numpy as np def color_space( img ): gray_img = ...

  7. swift基础语法之——变量和常量

    swift使用let关键字来定义常量,使用var来定义变量,变量在使用前必须初始化(赋初始值) swift是类型安全语音,即不同类型的变量不能一起运算,必须转成同一类型才可以 变量的类型在声明时不必给 ...

  8. [比赛|考试]nowcoder NOIPpj组第二场

    nowcoder NOIPpj组第二场 370pts/400pts(100,100,100,70) rank3 给自己的反思:前3题都A了,T4O(N^2)不会就是不会(没准是我懒得推了),DP了70 ...

  9. [C/C++语言标准] ISO C99/ ISO C11/ ISO C++11/ ISO C++14/ISO C++17 Downloads

    语言法典,C/C++社区人手一份,技术讨(hu)论(peng)必备 ISO IEC C99 https://files.cnblogs.com/files/racaljk/ISO_C99.pdf IS ...

  10. C++在WINdow桌面绘制文字图形

    [起因] 最近碰到一个项目,需要在电脑左面显示一些信息,因此在网上找了一些资料,成功实现在桌面绘制信息. [代码] #include "stdafx.h" #include < ...