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配置的地址 ...
随机推荐
- 防止开发人员获取到敏感数据(SQL Server的数据加密简介)
背景 有时候,我们还真的会碰到这样的需求:防止开发人员获取到敏感数据.也许你觉得很简单,把开发和运营分开不就可以了吗?是的,如果公司有专门的运营团队的话,但对于很多小公司来说,几个人的开发团队就兼顾了 ...
- CocoSocket开源下载与编写经验分享
CocoSocket分享 cocos2dx 3.1都出了,但依然没有发现与它原生的SOCKET支持,于是,这几天在家,手工撸了一个. 目前版本对IOS,ANDROID,WINDOWS支持良好.且为异步 ...
- synchronized同步对象锁
package com.system.util; import com.common.Constants; import com.util.Cache; /** * 创建同步对象锁 * * @auth ...
- IOS 手势-轻点、触摸、手势、事件
1.概念 手势是从你用一个或多个手指接触屏幕时开始,直到手指离开屏幕为止所发生的所有事件.无论手势持续多长时间,只要一个或多个手指仍在屏幕上,这个手势就存在. 触摸是指把手指放到IOS设备的屏幕上,从 ...
- 从双十一战报看传统大家电如何O2O转型?
说到大家电电商,大家都会想起天猫.京东.苏宁易购.国美在线等各大电商平台,他们这一次的双十一又实现了较大规模的增长,而各大电商平台家电辉煌战绩的背后实际上是各大品牌家电的成功. 格力今年双十一当天创下 ...
- Ajax技术
1.ajax技术的背景 不可否认,ajax技术的流行得益于google的大力推广,正是由于google earth.google suggest以及gmail等对ajax技术的广泛应用,催生了ajax ...
- javascript_core_01之数据类型与运算
1.数据类型转换: ①隐式转换:程序根据需要,自动转化数据类型: ②强制转换:主动调用函数执行转换: 2.字符串强制转换: ①x.toString():不能转换null和undefined: ②Str ...
- Sqlserver 中exists 和 in
如图,现在有两个数据集,左边表示#tempTable1,右边表示#tempTable2.现在有以下问题: 1.求两个集的交集? 2.求tempTable1中不属于集#tempTable2的集? 先创建 ...
- Mybatis中SqlMapper配置的扩展与应用(3)
隔了两周,首先回顾一下,在Mybatis中的SqlMapper配置文件中引入的几个扩展机制: 1.引入SQL配置函数,简化配置.屏蔽DB底层差异性 2.引入自定义命名空间,允许自定义语句级元素.脚本级 ...
- 让我们一起写出更有效的CSharp代码吧,少年们!
周末空闲,选读了一下一本很不错的C#语言使用的书,特此记载下便于对项目代码进行重构和优化时查看. Standing On Shoulders of Giants,附上思维导图,其中标记的颜色越深表示在 ...