[札记]IL经典指令解析之方法调度
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经典指令解析之方法调度的更多相关文章
- IL中间语言指令大全
一些 IL 语言指令解释: Public field Static Beq 如果两个值相等,则将控制转移到目标指令.Public field Static Beq_S ...
- AngularJS 指令解析(二)
AngularJS 指令解析(二) 第一篇我们讲过了作用域(scope)这块内容,现在我们进入正题,讲AngularJS的指令. 什么是指令? 这里我们引用官方的一句话: Custom directi ...
- AngularJS 指令解析(一)
AngularJS 指令解析(一) 前言 笔者AngularJS接触时间差不多是两年多,虽然这两年多AngularJS版本日新月异,但是笔者的版本是比较老的1.4.3,一方面是自己对这个版本比较熟悉, ...
- .NET中常用的几种解析JSON方法
一.基本概念 json是什么? JSON:JavaScript 对象表示法(JavaScript Object Notation). JSON 是一种轻量级的数据交换格式,是存储和交换文本信息的语法. ...
- Java学习笔记之方法重载,动态方法调度和抽象类
一.方法重载 如果子类中的方法与它的超类中的方法有相同的方法名,则称子类中的方法重载超类中的方法,特别是当超类和子类中的方法名和参数类型都相同时,在子类中调用该方法时,超类中的方法会被隐藏.考虑下面程 ...
- C# 解析js方法,并调用js方法
本文转载:http://www.cnblogs.com/StudyLife/archive/2013/03/11/2953516.html 本文不是基于B/S的 后台调用前台js方法,而是给你一段js ...
- 017——VUE中v-fo指令的使用方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Dockerfile的书写规则和指令的使用方法
Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令.Docker程序将这些Dockerfile指令翻译真正的Linux命 ...
- securecrt中进入uboot命令行时,出现无法键入任何指令的问题解决方法
securecrt中进入uboot命令行时,出现无法键入任何指令的问题解决方法 可能出现以下几种情况 1.securecrt在创建连接时,忘记取消勾选流控: 2.usb转串口线坏了3.uboot有问题 ...
随机推荐
- GMT and CST
GMT(Greenwich Mean Time) 代表格林尼治标准时间 而CST却同时可以代表如下 4 个不同的时区: Central Standard Time (USA) UT-6:00 C ...
- BZOJ 3295 动态逆序对
调了好久.... 转化成三维偏序,cdq处理. 好像比较快? #include<iostream> #include<cstdio> #include<cstring&g ...
- Dom文档模型
文档对象模型 通过 JavaScript,您可以重构整个 HTML 文档.您可以添加.移除.改变或重排页面上的项目.要改变页面的某个东西,JavaScript 就需要获得对 HTML 文档中所 ...
- lseek()函数
lseek()有个特殊的用途,确定文件是常规文件还是设备.<pre lang="c" escaped="true">off_t currpos;ou ...
- 使用Jquery Mobile设计Android通讯录
本系列教程将指导大家一步步使用Jquery Mobile设计一个Android的通讯录应用.其中在应用的界面部分,将使用jQuery Mobile框架,并且会指导大家如何使Android中提供的web ...
- 什么时候用copy什么时候用retain (一)
在声明一个property的时候总是搞不清什么时候用retain,什么时候用copy,用上去了感觉也不会错,但是又没有安全感: Copy:顾名思义,复制,将对象复制一份,ios内部的操作时,先copy ...
- hdu 5423 Rikka with Tree(dfs)bestcoder #53 div2 1002
题意: 输入一棵树,判断这棵树在以节点1为根节点时,是否是一棵特殊的树. 相关定义: 1. 定义f[A, i]为树A上节点i到节点1的距离,父节点与子节点之间的距离为1. 2. 对于树A与树B,如 ...
- 细雨学习笔记:JMeter 的主要测试组件总结
1. 测试计划是使用 JMeter 进行测试的起点,它是其它 JMeter 测试元件的容器. 2. 线程组代表一定数量的并发用户,它可以用来模拟并发用户发送请求.实际的请求内容在Sampler中定义, ...
- Eclipse安装配置PyDev插件
Eclipse安装配置PyDev插件 关于PyDev PyDev是一个功能强大的 Eclipse插件,使用户可用 Eclipse 来进行 Python 应用程序的开发和调试.PyDev 插件的出现方便 ...
- javascript的变态位运算
javascript的变态位运算 var a = "10" | 0; alert(a); alert (typeof a);结果为10,number. 这就是说这条语句可以将字符串 ...