上周末回家去享受生活了, 工作是为了更好的生活嘛, 所以我把生活, 工作分的比较开. 这几天不是很忙, 在学习工作技能的同时, 发点博文, 也算是做一个学习笔记

上篇中, 贴出的地址里面那位哥, 也有一篇值类型和引用类型的文章

来源:http://www.cnblogs.com/yingql/archive/2009/03/23/1420026.html

我这个和他的那个稍有不同, 各位看官, 请!

一、示例

public class Person
{
public string Name { get; set; } public int Age { get; set; }
} class Program
{
private Random rand = new Random(DateTime.Now.Millisecond); private Person person = new Person { Name = "Elvin", Age = }; private string pro = "pro"; private double dou = 3.14; static void Main(string[] args)
{
Console.WriteLine("Main");
Console.ReadKey();
}
}

反编译Program的构造函数, 代码如下:

public Program()
{
this.rand = new Random(DateTime.Now.Millisecond);
Person person = new Person {
Name = "Elvin",
Age = 0x1a
};
this.person = person;
this.pro = "pro";
this.dou = 3.14;
} .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack
.locals init (
[] class ConsoleApplication3.Person person,
[] valuetype [mscorlib]System.DateTime time) L_0000: ldarg. //加载this, 是一个地址, 将this沉底, 为一会的this.rand = new Random()服务
L_0001: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
L_0006: stloc. //初始化time, 为当前时间
L_0007: ldloca.s time //加载time的地址, 为什么加载地址呢, 一会详细介绍, 容我卖个关子 (1)
L_0009: call instance int32 [mscorlib]System.DateTime::get_Millisecond() //调用结构体Datetime的方法 L_000e: newobj instance void [mscorlib]System.Random::.ctor(int32) //new Random(), 将对象放入堆中, 然后把指向此对象的地址压栈
L_0013: stfld class [mscorlib]System.Random ConsoleApplication3.Program::rand //把刚刚得到的地址赋给rand, 实现this.rand = new Random()功能 L_0018: ldarg. //加载this地址,将this沉底, 为一会的this.person=person服务
L_0019: newobj instance void ConsoleApplication3.Person::.ctor() //new Person()
L_001e: stloc. //person = new Person(), 这里的person并不是this.person, 注意
L_001f: ldloc. //加载person, 为什么此处是用的ldloc, 而不是ldloca呢? 答案马上揭晓
L_0020: ldstr "Elvin" //加载 "Elvin" 字符串
L_0025: callvirt instance void ConsoleApplication3.Person::set_Name(string) //person.Name = "Elvin"
L_002a: nop L_002b: ldloc.
L_002c: ldc.i4.s 0x1a
L_002e: callvirt instance void ConsoleApplication3.Person::set_Age(int32)
L_0033: nop L_0034: ldloc. //加载person, 不是this.person
L_0035: stfld class ConsoleApplication3.Person ConsoleApplication3.Program::person //给this.person赋值, this.person=person L_003a: ldarg. //加载this, 这里加载this做什么? (2)
L_003b: ldstr "pro" //加载"pro"字符串
L_0040: stfld string ConsoleApplication3.Program::pro //this.pro = "pro" L_0045: ldarg.
L_0046: ldc.r8 3.14
L_004f: stfld float64 ConsoleApplication3.Program::dou
L_0054: ldarg.
L_0055: call instance void [mscorlib]System.Object::.ctor()
L_005a: nop
L_005b: ret
}

例子大家应该都能看得懂, 下面就揭晓上面的包袱

二、注意的点

在揭晓答案之前, 首先得开一扇窗户.

大家应该都知道, 值类型、引用类型是怎么存储的吧, 多的就不解释了, 上一幅图吧

2. stfld -- 好吧, 在讲第1点之前, 我还是想先将第2点

先看stfld的工作原理, 即堆栈转换行为如下:

按照先后顺序:

  1.将一个对象引用或指针压入堆栈

  2.将值压入堆栈

  3.该值和对象的引用/指针从堆栈中弹出,对象的字段更新为替换的值

详细分析 : http://www.cnblogs.com/jackson0714/p/4995948.html

从上面可以看出, 是需要传地址的, 先传地址, 在传值, 接着调用stfld指令, 才能完成赋值操作, 所以这里传了个ldarg.0, 来完成this.pro="pro"功能

1. ldloc 与 ldloca

从上面的例子, 看到在使用Person的时候, 用的ldloc, 而使用DateTime的时候, 却使用了ldloca, 此处就能体现引用类型和值类型的区别了.

在调用方法的时候, 由于引用类型在栈中, 存放的就是地址, 所以可以直接实现调用内部方法的功能,

而值类型并不是直接存放地址的, 所以在调用内部方法的时候, 其实是传地址来实现此功能的.

对象,结构体(值类型本质也是结构体, 如:int, decimal)在调用自身方法/属性/字段的时候, 都是通过传递地址的方式来调用的. time.Year(), 此处的time就是地址, person.Name, 此处的person也是一个地址

这哥们对IL有一个比较详细的介绍:http://www.cnblogs.com/jackson0714/p/DotNET_IL3.html#_label4

Emit学习(2) - IL - 值类型和引用类型(补)的更多相关文章

  1. C#学习笔记之值类型与引用类型

    [TOC] C#学习笔记之值类型与引用类型 1.值类型与引用类型 1.1 深层区别 值类型与引用类型有不同的内存分布,这导致了不同的内存管理机制: 值类型由OS负责内存管理 引用类型由垃圾回收器(GC ...

  2. 学习记录 java 值类型和引用类型的知识

    1. Java中值类型和引用类型的不同? [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值, 那么调用这个方法是传入的变量的值也将改变 ...

  3. 【C#】学习笔记(4) 值类型和引用类型相关(Null相关)

    Reference and Value Types Value Types(值类型): struct(结构体) 独立的实例或者是拷贝 值的改变不会影响其它拷贝 值就是它所代表的信息 没有引用,所以不可 ...

  4. C#学习笔记(基础知识回顾)之值类型和引用类型

    一:C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存 ...

  5. .net学习之.net和C#关系、运行过程、数据类型、类型转换、值类型和引用类型、数组以及方法参数等

    1..net 和 C# 的关系.net 是一个平台,C#是种语言,C#语言可以通过.net平台来编写.部署.运行.net应用程序,C#通过.net平台开发.net应用程序2..net平台的重要组成FC ...

  6. C#学习笔记(三):值类型、引用类型及参数传递

    值类型和引用类型简介 C#中存在两种数据类型,分别是值类型与引用类型,下面我们来看看这两种类型的区别. 值类型主要包括: 简单类型(如int.float.char等,注意string不是值类型): 枚 ...

  7. c#学习基础(2)存储、值类型和引用类型、变量

    程序运行时,它的数据必须存储在内存中,数据项需要多大的内存.存储在什么地方以及如何存储都依赖该数据项的类型 运行中的程序使用两个区域来存储数据:栈和堆 栈是一个内存数组,是一个LIFO(last in ...

  8. Net基础篇_学习笔记_第十二天_面向对象继承(命名空间 、值类型和引用类型)

    命名空间可以认为类是属于命名空间的. 解决类的重名问题,可以看做类的“文件夹”如果在当前项目中没有这个类的命名空间,需要我们手动的导入这个类所在的命名空间.1).用鼠标去点2).alt+shift+F ...

  9. 从CLR角度来看值类型与引用类型

    前言 本文中大部分示例代码来自于<CLR via C# Edition3>,并在此之上加以总结和简化,文中只是重点介绍几个比较有共性的问题,对一些细节不会做过深入的讲解. 前几天一直忙着翻 ...

随机推荐

  1. MapReduce实例浅析

    在文章<MapReduce原理与设计思想>中,详细剖析了MapReduce的原理,这篇文章则通过实例重点剖析MapReduce 本文地址:http://www.cnblogs.com/ar ...

  2. 走进AngularJs(三)自定义指令-----(上)

    一.有感而发的一些话 在学习ng之前有听前辈说过,angular上手比较难,初学者可能不太适应其语法以及思想.随着对ng探索的一步步深入,也确实感觉到了这一点,尤其是框架内部的某些执行机制,其复杂程度 ...

  3. 【摘选引用】在安全的SQL 密码也不过如此

    SQL密码再安全也禁不住破解!!! http://www.sqlservercentral.com/articles/password+cracking/96540/ 备注:[摘选引用]是本人日常收集 ...

  4. (小常识)Dictionary的遍历

                Dictionary<int, string> objDictionary = new Dictionary<int, string>();       ...

  5. CSS3 动画一瞥

    伴随HTML5而来的CSS3让前端大湿们可以用简单的CSS样式即可写出动画效果来,而在这之前,一提到动画我们可能会想到JavaScript,Flash,Java插件等.如果是用JavaScript那倒 ...

  6. java自定义注解实现前后台参数校验

    2016.07.26 qq:992591601,欢迎交流 首先介绍些基本概念: Annotations(also known as metadata)provide a formalized way ...

  7. 分割超大Redis数据库例子

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/124.html?1455853509 薄荷 App 上的伙伴功能大量使用了 ...

  8. MVVM架构~mvc,mvp,mvvm大话开篇

    返回目录 百度百科的定义: MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新 ...

  9. ELK日志应用平台搭建

    ELK架构: ElasticSearch:用于存储.索引日志. Logstash:用于收集.处理和转发事件或日志信息的工具. Kibana:搜索和可视化的日志的WEB界面. ELK优点: a.处理方式 ...

  10. D3.js 学习( 一)

    <html> <head> <meta charset="utf-8"> <title>第三课:为柱形图添加坐标轴</titl ...