上一篇的介绍中, 并没有介绍到对象的创建过程, 这一篇主要就介绍一下, 对象的创建过程.

其实熟悉了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 - 对象的创建过程的更多相关文章

  1. 图解JAVA对象的创建过程

    前面几篇博文分别介绍了JAVA的Class文件格式.JVM的类加载机制和JVM的内存模型,这里就索性把java对象的创建过程一并说完,这样java对象的整个创建过程就基本上说明白了(当然你要有基础才能 ...

  2. HttpApplication 对象的创建过程及HttpModule过滤器的内部实现过程

    最近通过Reflector学习了一下asp.net内部的原理,做做笔记,方便以后查阅. 先看下HttpApplication 对象的创建过程 从IHttpHandler applicationInst ...

  3. JVM中对象的创建过程

    JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...

  4. 对象的创建过程(chapter5.7.3)

    总结一下对象的创建过程,假设有一个名为Dog的类: 1. 即使没有显示地使用static关键字,构造器实际上也是静态的方法,因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类 ...

  5. 2 Java对象的创建过程

    JAVA中创建对象直接new创建一个对象,对么对象的创建过程是怎样的呢? 程序运行过程中有许多的对象被创建出来.那么对象是如何创建的呢? 一 对象创建的步骤 1 遇到new指令时,检查这个指令的参数是 ...

  6. 深入理解Java对象的创建过程:类的初始化与实例化

    摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...

  7. JAVA虚拟机:对象的创建过程

    简要说明的话,Java对象的创建过程分为下面几步: 1.执行相关检查: 2.为对象分配内存,将分配到的内存空间都初始化为零值: 3.进行构造代码块和构造函数的初始化 下面详细介绍这几个步骤: 1.执行 ...

  8. java中对象的创建过程

    public class Test1 { public static void main(String[] args) { new B(); System.out.println("---- ...

  9. 类加载过程&对象的创建过程

    类加载过程 1.JVM发现要使用一个类,首先要到方法区中找:如果找到了,就直接使用,如果没有找到,才会去找这个类的class文件,然后加载: (在找class文件时,是根据classpath配置的地址 ...

随机推荐

  1. Hadoop日记Day12---MapReduce学习

    一.MapReduce简介 1.1MapReduce概述 MapReduce是一种分布式计算模型,由Google提出,主要用于搜索领域,解决海量数据的计算问题.MR由两个阶段组成:Map和Reduce ...

  2. shell脚本常规技巧

    邮件相关 发送邮件: #!/usr/bin/python import sys; import smtplib; from email.MIMEText import MIMEText mail_ho ...

  3. [FPGA] 1、开发板使用和引脚连接

    目录 1.注意事项 2.设备简介 3.引脚分配 注意事项: ① 插拔下载线时必须断电! ② Quartus II 软件和 NIOS 软件的版本必须一致,并安装在同一个目录下面,安装目录不要有中文和空格 ...

  4. JavaScript字符转Unicode,顺便说句:GitHub的Oh no页面很亮

    遇到个输不出来的字符怎么办,因为输不出来的字符一般又是不常见大多数时候连名字也喊不出来的,所以想问百度谷歌大大也不大可能.如果是小白用户肯定会去把输入法软盘打开切换到其他键盘一个一个找.即使有搜狗输入 ...

  5. .NET Framework中重点类型的继承关系

    继承关系 Object ├─Array │ └─T[] ├─ArrayList ├─List<T> └─String 集合类型的接口 下图展示了集合类型的各种接口的相互关系.注意,下图中所 ...

  6. IOS 公共类-数字处理

    1.写一个方法,调用的时候交换两个数的值 -(void) swap:(int*)a andNumber:(int*)b{ int temp = *a; *a = *b; *b = temp; } 调用 ...

  7. lua二进制操作函数

    由于 Lua 脚本语言本身不支持对数字的二进制操作(例如 与,或,非 等操作),MUSHclient 为此提供了一套专门用于二进制操作的函数,它们都定义在一个“bit”表中,使用时只要requre “ ...

  8. Constraint1:主键约束,唯一性约束和唯一索引

    1,主键约束创建索引 作为Primay Key的列是唯一的,非空的,Sql Server在创建主键约束时,自动为主键列创建一个唯一索引,并且索引列不允许为null. create table dbo. ...

  9. CSS3妙用

    scaleX的妙用 案例1 效果: HTML: <a href="javascript:;">我有下划线噢</a> CSS: a{ text-decorat ...

  10. 绘制 ToggleButton --重写view

    package com.example.compoundbuttonview.view; import com.example.compoundbuttonview.R; import android ...