Emit学习(2) - IL - 对象的创建过程
上一篇的介绍中, 并没有介绍到对象的创建过程, 这一篇主要就介绍一下, 对象的创建过程.
其实熟悉了IL语法之后, 完全可以用Reflector反编译代码去查看. 而且正因为有这个工具, 可以对照着Reflecotr中的IL代码去写Emit的IL.
好了, 开始正题了, 还是从实例开始:
一、示例
首先建类(Person, Contacts):
public class Person
{
public string Name { get; set; } public int Age { get; set; } public Contacts Contact { get; set; } public override string ToString()
{
return string.Format("Name:{0}\r\nAge:{1}\r\nContact:{2}", this.Name, this.Age, this.Contact.ToString());
}
} public class Contacts
{
public string Address { get; set; } public string Phone { get; set; } public string QQ { get; set; } public override string ToString()
{
var res = string.Format(@"[Address:{0}, Phone:{1}, QQ:{2}]", this.Address, this.Phone, this.QQ);
return res;
}
}
然后就可以写创建方法了:
static void PersonTest()
{
var contacts = new Contacts { Address="HeFei", Phone="", QQ=""};
var person = new Person { Name = "Wubi", Age = , Contact = contacts };
Console.WriteLine(person.ToString());
}
反编译后的IL代码如下:
.method private hidebysig static void PersonTest() cil managed
{
.maxstack
.locals init (
[] class ConsoleApplication1.Contacts contacts,
[] class ConsoleApplication1.Person person,
[] class ConsoleApplication1.Contacts contacts2,
[] class ConsoleApplication1.Person person2) L_0000: nop
L_0001: newobj instance void ConsoleApplication1.Contacts::.ctor()
L_0006: stloc. L_0007: ldloc.
L_0008: ldstr "HeFei"
L_000d: callvirt instance void ConsoleApplication1.Contacts::set_Address(string) //contacts2.Address = "HeFei" L_0012: nop
L_0013: ldloc.
L_0014: ldstr ""
L_0019: callvirt instance void ConsoleApplication1.Contacts::set_Phone(string) L_001e: nop
L_001f: ldloc.
L_0020: ldstr ""
L_0025: callvirt instance void ConsoleApplication1.Contacts::set_QQ(string) L_002a: nop
L_002b: ldloc.
L_002c: stloc. //contacts = contacts2 L_002d: newobj instance void ConsoleApplication1.Person::.ctor()
L_0032: stloc.
L_0033: ldloc.
L_0034: ldstr "Wubi"
L_0039: callvirt instance void ConsoleApplication1.Person::set_Name(string) L_003e: nop
L_003f: ldloc.
L_0040: ldc.i4.s
L_0042: callvirt instance void ConsoleApplication1.Person::set_Age(int32) L_0047: nop
L_0048: ldloc.
L_0049: ldloc.
L_004a: callvirt instance void ConsoleApplication1.Person::set_Contact(class ConsoleApplication1.Contacts) L_004f: nop
L_0050: ldloc.
L_0051: stloc.
L_0052: ldloc. L_0053: callvirt instance string [mscorlib]System.Object::ToString()
L_0058: call void [mscorlib]System.Console::WriteLine(string)
L_005d: nop
L_005e: ret
}
二、补充的点
可能有人注意到了, 此处调用方法时, 用的并不是Call, 而是 Callvirt, 什么时候用Call, 什么时候用Callvirt呢?
首先, 我们看callvirt出现的位置, 是出现在public string Name{get;set;}中的, get, set其实是两个方法, 大家都知道的, 所以在给属性赋值时, 其实是调用的方法, 所以这里赋值并不是用的stloc之类的
.method public hidebysig specialname instance void set_Name(string 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack
L_0000: ldarg. //非静态方法中, arg0指的是this
L_0001: ldarg. //arg1才是这里的'value'
L_0002: stfld string ConsoleApplication1.Person::<Name>k__BackingField
L_0007: ret
}
其次, 我们先从字面的意思去看着两个指令
Call 都知道是调用的意思, 那么Callvirt什么意思呢? 从前面的经验, 我想到, 这些指令并不是随便取的, 短到一个字母都是有特定意义的, 所以, 把Callvirt拆开来, 只看virt, 是不是有些熟悉的赶脚, 跟virtual这个单词比较一下, 就能明白Callvirt主要是调用那些方法了.
嘿嘿, 没有再次了哦, 下面是call和callvirt的一些区别:
1.call可以调用静态方法, 实例方法, 以及虚方法; 而callvirt只能调用实例方法和虚方法, 对于静态方法, 是心有余而力不足的
2.call一般是以非虚的方法来调用函数的, 而callvirt是以多态的方式来调用函数的.
至于异同的实例, 我就不给了, 大家可以看一下 : http://www.cnblogs.com/wang_yb/archive/2011/06/28/2092327.html
还有一个哥们也写过call与callvirt的区别 : http://www.cnblogs.com/yingql/archive/2009/03/23/1420000.html
网络时代就是好啊, 可以很容易的就能获取到别人的成果, 谢谢这些哥们了
Emit学习(2) - IL - 对象的创建过程的更多相关文章
- 图解JAVA对象的创建过程
前面几篇博文分别介绍了JAVA的Class文件格式.JVM的类加载机制和JVM的内存模型,这里就索性把java对象的创建过程一并说完,这样java对象的整个创建过程就基本上说明白了(当然你要有基础才能 ...
- HttpApplication 对象的创建过程及HttpModule过滤器的内部实现过程
最近通过Reflector学习了一下asp.net内部的原理,做做笔记,方便以后查阅. 先看下HttpApplication 对象的创建过程 从IHttpHandler applicationInst ...
- JVM中对象的创建过程
JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...
- 对象的创建过程(chapter5.7.3)
总结一下对象的创建过程,假设有一个名为Dog的类: 1. 即使没有显示地使用static关键字,构造器实际上也是静态的方法,因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类 ...
- 2 Java对象的创建过程
JAVA中创建对象直接new创建一个对象,对么对象的创建过程是怎样的呢? 程序运行过程中有许多的对象被创建出来.那么对象是如何创建的呢? 一 对象创建的步骤 1 遇到new指令时,检查这个指令的参数是 ...
- 深入理解Java对象的创建过程:类的初始化与实例化
摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...
- JAVA虚拟机:对象的创建过程
简要说明的话,Java对象的创建过程分为下面几步: 1.执行相关检查: 2.为对象分配内存,将分配到的内存空间都初始化为零值: 3.进行构造代码块和构造函数的初始化 下面详细介绍这几个步骤: 1.执行 ...
- java中对象的创建过程
public class Test1 { public static void main(String[] args) { new B(); System.out.println("---- ...
- 类加载过程&对象的创建过程
类加载过程 1.JVM发现要使用一个类,首先要到方法区中找:如果找到了,就直接使用,如果没有找到,才会去找这个类的class文件,然后加载: (在找class文件时,是根据classpath配置的地址 ...
随机推荐
- Spring AOP简述
使用面想对象(Object-Oriented Programming,OOP)包含一些弊端,当需要为多个不具有继承关系的对象引入公共行为时,例如日志,安全检测等.我们只有在每个对象中引入公共行为,这样 ...
- JavaScript使用DeviceOne开发实战(三)仿微信应用
这是一个系列的文档,长期目标是利用DeviceOne开发一些目前使用广泛的优质手机应用,我们会最大化的实现这些应用的每一个功能和细节,不只停留在简单的UI模仿和Demo阶段,而是一个基本可以使用的实际 ...
- Ehcache BigMemory: 摆脱GC困扰
问题 使用java开源项目经常需要调优jvm,以优化gc.对于gc,如果对象都是短时对象,那么jvm相对容易优化,假如碰上像solr使用自带java cache的项目,那么gc严重受限于cache,因 ...
- 虚拟化平台cloudstack(5)——参考资料
虚拟化的几种方式 完全虚拟化: 半虚拟化: 硬件辅助虚拟化: 详细的内容可以看: http://pan.baidu.com/share/link?shareid=4134188256&uk=2 ...
- ./在Linux下是什么意思
在网上找的答案: . 在这里表示的是当前目录,就像 .. 表示上级目录一样. 这个 / 表示的是目录级别的分隔符,他之前的就是目录名,./aaa/ 表明的就是 . (也就是当前目录)下面的 aaa 目 ...
- 每天一个linux命令(8):cp 命令
cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参数.但是如果是 ...
- gulp/grunt和browserify/webpack的区别
Gulp应该和Grunt比较,他们的区别我就不说了,说说用处吧.Gulp / Grunt 是一种工具,能够优化前端工作流程.比如自动刷新页面.combo.压缩css.js.编译less等等.简单来说, ...
- Javascript单元测试之QUnit
首先去Qunit官网下载. Qunit有一个js脚本文件和一个css我们在页面中引入它. <script src="qunit-2.0.1.js"></scrip ...
- Android_TextView之跑马灯效果
对于android控件中的TextView,相信大家一定不陌生,在显示文本内容时十分方便.不过我在使用时遇到一个小问题,就是当文字交多时,如何为用户进行展示.今天就为大家介绍一种解决方案--跑马灯效果 ...
- 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案
作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模 ...