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配置的地址 ...
随机推荐
- 微软颜龄Windows Phone版开发小记
随着微软颜龄中文网cn.how-old.net的上线,她也顺势来到了3大移动平台. 用户在微软颜龄这一应用中选择一张包含若干人脸的照片,就可以通过云计算得到他们的性别和年龄. 今天我们就和大家分享一下 ...
- JavaScript工具库之Lodash
你还在为JavaScript中的数据转换.匹配.查找等烦恼吗?一堆看似简单的foreach,却冗长无趣,可仍还在不停的repeat it!也许你已经用上了Underscore.js,不错,你已经进步很 ...
- 使用ACE_Task管理线程
为什么要使用ACE_Task来管理线程 从C#转到C++后,感觉到C++比C#最难的地方,就是在系统编程时,C#中有对应的类库,我接触到一个类后,就可以通过这个类,知道很多相关的功能.而在C++中,必 ...
- [安卓] 14、安卓HTTP——POST和GET用法分析
内容简介 本文通过建立一个简单的Servlet服务器来分析安卓上用HTTP和服务器通信的细节,旨在演示C/S模式下服务器端和客户端的工作过程. 目录 part.1 用MyEclipse建立一个简单的s ...
- Java基础类型总结
最近一直在总结反思自己, 趁着现在请假在学校上课的空余时间,从基础开始重新温故学习下Java,充实下自己. 一.数据类型 从下图中,我们可以很清晰的看出Java中的类型,其中红色方框中的是Java的4 ...
- Dynamics CRM 2013 installation
原创地址:http://www.cnblogs.com/jfzhu/p/3445820.html 转载请注明出处 一 硬件要求 1. CRM Server 下表对硬件的要求是假定Microsoft S ...
- (转)Hibernate事务管理
Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰.作为一名软件设计 ...
- IOS Animation-CABasicAnimation例子(简单动画实现)
这些例子都是CABasicAnimation的一些简单实现的动画,例如移动.透明度.翻转等等.方法里面传入一个CALayer类或者子类就可以了. 下面是用swift实现的,这些方法我们也可以用作公共类 ...
- 360路由器刷openwrt后设置wifi中继
上一篇文章(360路由器刷openwrt.不死uboot.双系统 .wifi中继 - 飞鸿影~ - 博客园)讲了如何在360路由器C301上安装openwrt以及安装双系统.这篇文章讲如何设置无线中继 ...
- 据说,每一个 iOSer 都想要一张 Swift 大会门票
据说,每一个 iOSer 都想要一张中国首届 Swift 开发者大会的门票: 那么,福利来了-- fir.im 作为中国首届 Swift 大会的唯一钻石赞助商,有最后 2 张价值 600 多的门票(已 ...