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. IL中间语言指令大全

    一些 IL 语言指令解释: Public field Static     Beq     如果两个值相等,则将控制转移到目标指令.Public field Static     Beq_S     ...

  2. AngularJS 指令解析(二)

    AngularJS 指令解析(二) 第一篇我们讲过了作用域(scope)这块内容,现在我们进入正题,讲AngularJS的指令. 什么是指令? 这里我们引用官方的一句话: Custom directi ...

  3. AngularJS 指令解析(一)

    AngularJS 指令解析(一) 前言 笔者AngularJS接触时间差不多是两年多,虽然这两年多AngularJS版本日新月异,但是笔者的版本是比较老的1.4.3,一方面是自己对这个版本比较熟悉, ...

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

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

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

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

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

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

  7. 017——VUE中v-fo指令的使用方法

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. Dockerfile的书写规则和指令的使用方法

    Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令.Docker程序将这些Dockerfile指令翻译真正的Linux命 ...

  9. securecrt中进入uboot命令行时,出现无法键入任何指令的问题解决方法

    securecrt中进入uboot命令行时,出现无法键入任何指令的问题解决方法 可能出现以下几种情况 1.securecrt在创建连接时,忘记取消勾选流控: 2.usb转串口线坏了3.uboot有问题 ...

随机推荐

  1. POJ3415 Common Substrings

    后缀数组 求长度不小于k的公共子串的个数 代码: #include <stdio.h> #include <string.h> ; int len, len1; int wa[ ...

  2. 【转载】Javascript中的this关键字

    看了这篇文章 http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html 分情况讨论. 情况一:纯粹的函数 ...

  3. jQuery 清除div内容

    $.ajax({            url: "SearchSN.aspx",            data: "SN=" + $("#txtS ...

  4. 使用Jenkins构建持续集成环境

    简介 Jenkins是一个开源的持续集成工具,提供了数百种插件供用户选择,能够完成整套持续集成环境的构建. 它具有如下的特点: 持续集成和持续发布 作为可扩展的自动服务器,Jenkins可以作为简单的 ...

  5. POJ 3211 Washing Clothes【01背包】

    题意:给出n种颜色,m件衣服,再分别给出m件衣服的颜色,和洗所需要的时间,dearboy和他的妹子一起洗衣服,且同种颜色的衣服不能同时洗,也不能两个人同时洗一件衣服,问洗完这m件衣服至少需要的时间 先 ...

  6. HDU 1158 Employment Planning【DP】

    题意:给出n个月,雇佣一个人所需的钱hire,一个人工作一个月所需要的钱salary,解雇一个人所需要的钱fire,再给出这n个月每月1至少有num[i]个人完成工作,问完成整个工作所花费的最少的钱是 ...

  7. 深入理解OpenERP的工作流(Workflow)

    一.工作流定义: <?xml version="1.0"?>  <terp><data>    <record model="w ...

  8. 几个排序算法的JS实现

    最近找工作,复习一下数据结构的知识,看到排序这一块,顺便动手改了一下. 直接插入排序: 插入排序就是把数据分为有序区和无序区,遍历到的数据和有序区域的数据进行比较,找到要插入的位置,插入位置后的数据做 ...

  9. php 换行 PHP_EOL变量

    一个小小的换行,其实在不同的平台有着不同的实现,为什么要这样,可以是世界是多样的. 本来在unix世界换行就用/n来代替,但是windows为了体现他的不同,就用/r/n,更有意思的是在mac中用/r ...

  10. 正则表达式 java版

    众所周知,在程序开发中,难免会遇到需要匹配.查找.替换.判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力.因此,学习及使用正则表达式,便成了解决这一矛 ...