本篇讲述怎样装箱拆箱。装箱和拆箱都是针对值类型而言的,装箱的性能开销远比拆箱的性能开销大。

装箱
装箱指令是Box。使用格式是
ILGenerator.Emit(OpCodes.Box,<值类型>);
装箱当然是对一个值类型装箱的,所以第二个参数一定是int,float等一类的值类型。
实例:

ilGenerator.Emit(OpCodes.Box,typeof(int));

拆箱

拆箱指令是OpCodes.Unbox_Any和OpCodes.Unbox。他们的区别是Unbox指令不包含伴随着拆箱的字段复制操作,但是Unbox_Any则包含伴随着拆箱的字段复制操作。OpCodes.Unbox一般不用,所以这里不讲解它。
OpCodes.Unbox_Any的格式是
ILGenerator.Emit(OpCodes.Unbox_Any,<值类型>);
拆箱也是对一个值类型装箱的,所以第二个参数也是值类型。

拆箱也是对一个值类型装箱的,所以第二个参数也是值类型。
实例:

ilGenerator.Emit(OpCodes.Unbox_Any, typeof(double));

生成C#程序为

object obj = ;
Console.WriteLine(obj);
int value = (int)obj;
Console.WriteLine(value);
object obj2 = 1.7976931348623157E+308;
Console.WriteLine(obj2);
double value2 = (double)obj2;
Console.WriteLine(value2);

完整程序如下:

using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
/// <summary>
/// 装箱拆箱
/// </summary>
class Demo14_BoxUnBox
{
static string binaryName = "Demo14_BoxUnBox.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "BoxUnBox"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static ILGenerator ilGenerator; static void Emit_Codes()
{
LocalBuilder loca1 = ilGenerator.DeclareLocal(typeof(object));
LocalBuilder loca2 = ilGenerator.DeclareLocal(typeof(int)); LocalBuilder loca3 = ilGenerator.DeclareLocal(typeof(object));
LocalBuilder loca4 = ilGenerator.DeclareLocal(typeof(double)); ilGenerator.Emit(OpCodes.Ldc_I4, int.MaxValue);
ilGenerator.Emit(OpCodes.Box,typeof(int));
ilGenerator.Emit(OpCodes.Stloc_0);
ilGenerator.Emit(OpCodes.Ldloc_0);
ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }));
ilGenerator.Emit(OpCodes.Ldloc_0);
ilGenerator.Emit(OpCodes.Unbox_Any, typeof(int));
ilGenerator.Emit(OpCodes.Stloc_1);
ilGenerator.Emit(OpCodes.Ldloc_1);
ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) })); ilGenerator.Emit(OpCodes.Ldc_R8, double.MaxValue);
ilGenerator.Emit(OpCodes.Box, typeof(double));
ilGenerator.Emit(OpCodes.Stloc_2);
ilGenerator.Emit(OpCodes.Ldloc_2);
ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }));
ilGenerator.Emit(OpCodes.Ldloc_2);
ilGenerator.Emit(OpCodes.Unbox_Any, typeof(double));
ilGenerator.Emit(OpCodes.Stloc_3);
ilGenerator.Emit(OpCodes.Ldloc_3);
ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(double) }));
} public static void Generate()
{
InitAssembly(); typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public); /* 生成 public static void Main() */
GenerateMain(); Emit_Codes(); EmitReadKey();
ilGenerator.Emit(OpCodes.Ret); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); SaveAssembly();
Console.WriteLine("生成成功");
} static void EmitReadKey()
{
/* 生成 Console.ReadKey(); */
MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
ilGenerator.Emit(OpCodes.Call, readKeyMethod);
ilGenerator.Emit(OpCodes.Pop);
} static void GenerateMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { });
ilGenerator = mainMethod.GetILGenerator();
} static void InitAssembly()
{
AssemblyName assemblyName = new AssemblyName(namespaceName);
assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
} static void SaveAssembly()
{
Type t = typeBuilder.CreateType(); //完成Type,这是必须的
assemblyBuilder.Save(binaryName);
}
}
}

MSIL实用指南-装箱拆箱的更多相关文章

  1. box unboxing(装箱 拆箱) C#编程指南

    box(装箱)消耗大 box在堆栈中创建一个新的对象,性能消耗大 int i = 123; // Boxing copies the value of i into object o. object ...

  2. Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

    Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...

  3. 6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱

    引言 本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆:最后介绍值类型和引用类型,并 ...

  4. JAVA的自动装箱拆箱

    转自:http://www.cnblogs.com/danne823/archive/2011/04/22/2025332.html 蛋呢  的空间 ??什么是自动装箱拆箱 基本数据类型的自动装箱(a ...

  5. NET中的类型和装箱/拆箱原理

    谈到装箱拆箱,DebugLZQ相信给位园子里的博友一定可以娓娓道来,大概的意思就是值类型和引用类型的相互转换呗---值类型到引用类型叫装箱,反之则叫拆箱.这当然没有问题,可是你只知道这么多,那么Deb ...

  6. .net学习之继承、里氏替换原则LSP、虚方法、多态、抽象类、Equals方法、接口、装箱拆箱、字符串

    1.继承(1)创建子类对象的时候,在子类对象中会为子类对象的字段开辟空间,也会为父类的所有字段开辟空间,只不过父类私有的成员访问不到(2)子类从父类继承父类所有的非私有成员,但是父类的所有字段也会创建 ...

  7. Java中的装箱拆箱

    一)  装箱与拆箱 Java中有概念是一切皆对象,因为所有的类都默认继承自Object.但是,对于数据类型是个例外,如short,int,long,float,double, byte,char,bo ...

  8. Java 装箱 拆箱

    Java 自动装箱与拆箱   ??什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象的时候,我 ...

  9. Java 的自动装箱拆箱

    Java 是面向对象的语言,其基本数据类型也就有了相对应的类,称为包装类.以下是基本数据类型对应的包装类: 基本数据类型 包装类 byte(1字节) Byte short(2字节) Short int ...

随机推荐

  1. MyEclipse之Widget is disposed

    1 错误描述 2 错误原因 3 解决办法

  2. freemarker报错之五

    1.错误描述 freemarker.core.ParseException: Token manager error: freemarker.core.TokenMgrError: Lexical e ...

  3. Caused by: org.xml.sax.SAXParseException; lineNumber: 28; columnNumber: 81;

    1.错误描述 严重: Exception sending context initialized event to listener instance of class org.springframe ...

  4. 芝麻HTTP:非关系型数据库存储

    NoSQL,全称Not Only SQL,意为不仅仅是SQL,泛指非关系型数据库.NoSQL是基于键值对的,而且不需要经过SQL层的解析,数据之间没有耦合性,性能非常高. 非关系型数据库又可细分如下. ...

  5. How I explained OOD to my wife(转)

    How I explained OOD to my wife Learning Object Oriented Design principles through interesting conver ...

  6. Struts2【开发Action】知识要点

    前言 前面Struts博文基本把Struts的配置信息讲解完了.....本博文主要讲解Struts对数据的处理 Action开发的三种方式 在第一次我们写开发步骤的时候,我们写的Action是继承着A ...

  7. Fragment加载方式与数据通信

    一.加载方式 1. 静态加载 1.1 加载步骤 (1) 创建fragment:创建自定义Fragment类继承自Fragment类,同时将自定义Fragment类与Fragment视图绑定(将layo ...

  8. Redis进阶实践之十六 Redis大批量增加数据

    一.介绍      有时,Redis实例需要在很短的时间内加载大量先前存在或用户生成的数据,以便尽可能快地创建数百万个键.这就是所谓的批量插入,本文档的目标是提供有关如何以尽可能快的速度向Redis提 ...

  9. C++标准库bitset类型(简单使用方法)

    转自此人博客 ```cpp #include<bister> using std::bitset; ``` 一句话定义:可自定义位数,用作记录二进制的数据类型. 一,定义和初始化 ```c ...

  10. [BZOJ4034] [HAOI2015] T2 (树链剖分)

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所 ...