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. Balsamiq Mockups简单介绍(UI草图绘制工具)

    什么是Balsamiq Mockups Balsamiq Mockups出自加利福尼亚州的Balsamiq工作室,创始人Peldi在2008年6月推出了这款手绘风格的产品原型设计工具,并广受好评.2年 ...

  2. sed总结

    [-] 简介 调用方式 选项 命令集合 寻址方式 基本用法 文件操作 附加-插入-修改文本 删除文本 替换文本 转换文本 补充 ------------------------------------ ...

  3. Swustoj题目征集计划

    SWUST OJ题目征集计划   鉴于SWUST OJ长时间没有新题添加,题目数量和类型有限,同时也为加强同学们之间的算法交流,享受互相出题AC的乐趣,提高算法水平,现在启动题目征集计划啦~ 当你遇到 ...

  4. matlab中矩阵和向量的创建

    1.向量的创建 1)直接输入: 行向量:a=[1,2,3,4,5] 列向量:a=[1;2;3;4;5] 2)用“:”生成向量 a=J:K 生成的行向量是a=[J,J+1,…,K] a=J:D:K 生成 ...

  5. 【C#学习笔记】改变颜色

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. #1406 - Data too long for column (转)

    转自:(http://blog.sina.com.cn/s/blog_5115a74c01008e40.html) ERROR (): Data too long for column 解决方法 修改 ...

  7. 计算机网络——TCP与UDP协议详解

    根据应用程序的不同需求,运输层需要两种不同的运输协议,即面向连接的TCP和无连接的UDP. TCP:传输控制协议 TCP特点: 1)TCP是面向连接的运输层协议.所以,应用程序在使用TCP协议之前,必 ...

  8. 批量生成sqlldr文件,高速卸载数据

    SQL*Loader 是用于将外部数据进行批量高速加载的数据库的最高效工具,可用于将多种平面格式文件加载到Oracle数据库.SQL*Loader支持传统路径模式以及直接路径这两种加载模式.关于SQL ...

  9. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:4.安装Oracle RAC FAQ-4.4.无法图形化安装Grid Infrastructure

    无法图形化安装: [grid@linuxrac1 grid]$ ./runInstaller Starting Oracle Universal Installer... Checking Temp ...

  10. mysql 1130 ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this MySQL server

    mysql -u root -p  mysql;use mysql;  mysql;select 'host' from user where user='root';  mysql;update u ...