call、callvirt和calli指令用于完成方法调用,有何区别呢?

1)call使用静态调度,也就是根据引用类型的静态类型来调度方法。call指令根据引用变量的类型来调用方法,因此通常用于调用非虚方法。

2)callvirt使用虚拟调度,也就是根据引用类型的动态类型来调度方法;callvirt指令根据引用变量指向的对象类型来调用方法,执行时会递归的调用给自己知道堆栈溢出,从而实现了在运行时的动态绑定,因此通常用于调用虚方法。

3)calli又称间接调用,是通过函数指针来执行方法调用的。与call和callvirt相对应的(直接调用)

Father类

public class Father
    {
        public void DoWork()
        {
            Console.WriteLine("Father.DoWork()");
        }

        public virtual void DoVirtualWork()
        {
            Console.WriteLine("Father.DoVirtualWork()");
        }

        public virtual void DoVirtualAll()
        {
            Console.WriteLine("Father.DoVirtualAll()");
        }
    }

Son类

public class Son:Father
    {
        public static void DoStaticWork()
        {
            Console.WriteLine("Son.DoStaticWork()");
        }

        public new void DoWork()//new表示对父类的阻断
        {
            Console.WriteLine("Son.DoWork()");
        }

        public new virtual void DoVirtualWork()
        {
            Console.WriteLine("Son.DoVirtualWork()");
        }

        public override void DoVirtualAll()
        {
            base.DoVirtualAll();
            Console.WriteLine("Son.DoVirtualAll()");
        }
    }

GrandSon类

public class GrandSon:Son
    {
        public override void DoVirtualWork()
        {
            base.DoVirtualWork();
            Console.WriteLine("GrnadSon.DoVirtualWork()");
        }

        public override void DoVirtualAll()
        {
            base.DoVirtualAll();
            Console.WriteLine("GrandSon.DoVirtualAll()");
        }
    }

Prgram.cs

class Program
    {
        static void Main(string[] args)
        {
            Father son = new Son();
            son.DoWork();
            son.DoVirtualWork();

            Son.DoStaticWork();

            Father aGrandSon = new GrandSon();
            aGrandSon.DoWork();
            aGrandSon.DoVirtualWork();
            aGrandSon.DoVirtualAll();

            Console.ReadLine();
        }
    }

输出结果  

  

IL代码

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       61 (0x3d)
  .maxstack  1
  .locals init ([0] class ConsoleApplication1.Father son,
           [1] class ConsoleApplication1.Father aGrandSon)
  IL_0000:  nop
  IL_0001:  newobj     instance void ConsoleApplication1.Son::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance void ConsoleApplication1.Father::DoWork()
  IL_000d:  nop
  IL_000e:  ldloc.0
  IL_000f:  callvirt   instance void ConsoleApplication1.Father::DoVirtualWork()
  IL_0014:  nop
  IL_0015:  call       void ConsoleApplication1.Son::DoStaticWork()
  IL_001a:  nop
  IL_001b:  newobj     instance void ConsoleApplication1.GrandSon::.ctor()
  IL_0020:  stloc.1
  IL_0021:  ldloc.1
  IL_0022:  callvirt   instance void ConsoleApplication1.Father::DoWork()
  IL_0027:  nop
  IL_0028:  ldloc.1
  IL_0029:  callvirt   instance void ConsoleApplication1.Father::DoVirtualWork()
  IL_002e:  nop
  IL_002f:  ldloc.1
  IL_0030:  callvirt   instance void ConsoleApplication1.Father::DoVirtualAll()
  IL_0035:  nop
  IL_0036:  call       string [mscorlib]System.Console::ReadLine()
  IL_003b:  pop
  IL_003c:  ret
} // end of method Program::Main

  

[札记]IL经典指令解析之方法调度的更多相关文章

  1. .NET中常用的几种解析JSON方法

    一.基本概念 json是什么? JSON:JavaScript 对象表示法(JavaScript Object Notation). JSON 是一种轻量级的数据交换格式,是存储和交换文本信息的语法. ...

  2. Java学习笔记之方法重载,动态方法调度和抽象类

    一.方法重载 如果子类中的方法与它的超类中的方法有相同的方法名,则称子类中的方法重载超类中的方法,特别是当超类和子类中的方法名和参数类型都相同时,在子类中调用该方法时,超类中的方法会被隐藏.考虑下面程 ...

  3. C# 解析js方法,并调用js方法

    本文转载:http://www.cnblogs.com/StudyLife/archive/2013/03/11/2953516.html 本文不是基于B/S的 后台调用前台js方法,而是给你一段js ...

  4. angularjs(二)模板终常用的指令的使用方法

    通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的.ng的模板真是让我爱不释手.学习ng道路还很漫长,从模板 ...

  5. Emit学习(2) - IL - 常用指令介绍

    学习Emit必不可少的, 会使用到IL中间代码. 初见IL代码, 让我有一种汇编的感觉, 让我想起了, 大学时, 学习8051的汇编语言. 多的就不扯了, 直接进入正题, OpCodes指令集是不是有 ...

  6. U-BLOX GPS 模块及GPRMC指令解析

    受朋友所托,调试一款GPS模块,该模块是UBLOX的NEO-6M GPS模组.想到用这款GPS的人较多,自己日后也有可能在用到这个模块,就写下这份笔记. 1. 介绍 基本信息如下: 1, 模块采用U- ...

  7. SpringJDBC解析4-query方法

    重要步骤说明: 首先是从PersonServiceImpl方法进去,调用JdbcTemplate的query方法,然后执行一连串错中复杂的调用,而且里面有很多函数都是以回调形式处理, 1)JdbcTe ...

  8. Dapper使用方法:dapper-dot-net/Tests/Tests.cs解析(1)方法:TestMultiMapWithConstructor

    sql: SELECT * FROM users; SELECT * FROM posts; SELECT * FROM Posts p LEFT JOIN Users u ON u.Id= p.Ow ...

  9. PHP获取解析URL方法

    们要经常对url里面所带的参数进行解析,如果我们知道了url传递参数名称,例如: /index.php?name=tank&sex=1#top 我们就可以通过$_GET['name'],$_G ...

随机推荐

  1. myeclipse2014

    myeclipse 2014-GA offline  迅雷下载  http://downloads.myeclipseide.com/downloads/products/eworkbench/201 ...

  2. POJ2965

    #include <stdio.h> char map[4][4]; int map1[4][4]; int map2[4][4]; int num[16]; int min=1000,n ...

  3. 测试post接口curl

    function post($url,$data=array()) { if ( !empty($data) ) { $data=http_build_query($data); } $ch = cu ...

  4. Servlet3.0 jsp跳转到Servlet 出现404错误的路径设置方法

    最近又遇到了这种问题,百度了好久,发现有人说要在action的路径里面写Servlet文件的绝对路径,比如说,单独打开servlet的地址为http://localhost:8080/TomcatTe ...

  5. 【解决】SQL Server作业中Excel Application不能访问文件

    在通过SQL Server作业来实现定时任务时,出现如下错误: FullyQualifiedErrorId : ComMethodTargetInvocation使用“1”个参数调用“Add”时发生异 ...

  6. 网络编程2--毕向东java基础教程视频学习笔记

    Day 23 08 Udp接收端09 Udp键盘录入数据方式10 Udp聊天11 TCP传输12 TCP传输213 TCP练习14 TCP复制文件 08 Udp接收端 需求:定义一个应用程序,用于接收 ...

  7. jQuery File Upload跨域上传

    最近在做一个一手粮互联网项目,方案为前后端分离,自己负责前端框架,采用了Requirejs+avalonjs+jquery三个框架完成. 前后端通过跨域实现接口调用,中间也发现了不少问题,尤其是在富文 ...

  8. UICollectionView瀑布流的实现原理(转)

    http://ios.jobbole.com/85689/ 和使用 UIScollView 创刊一个瀑布流是一样的方式 7cc829d3gw1f4nq2oc09zj20j00hvq90.jpg 我的 ...

  9. IOS中的UINavigationController(导航控制器)

    UINavigationController UINavigationControlle:导航控制器,是iOS中最常用的多视图控制器之一,它用来管理多个试图控制器 导航控制器可以认为是管理控制器的控制 ...

  10. 盒模型padding和margin对滚动条位置的影响

    前置条件:盒模型样式overflow-y:scroll; ①padding-right:15px的效果: padding对于滚动条的位置显然是没有影响的,这也不是我们要的结果(这样很难看!) ②mar ...