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

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

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

拆箱

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

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

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

生成C#程序为

  1. object obj = ;
  2. Console.WriteLine(obj);
  3. int value = (int)obj;
  4. Console.WriteLine(value);
  5. object obj2 = 1.7976931348623157E+308;
  6. Console.WriteLine(obj2);
  7. double value2 = (double)obj2;
  8. Console.WriteLine(value2);

完整程序如下:

  1. using System;
  2. using System.Reflection;
  3. using System.Reflection.Emit;
  4.  
  5. namespace LX1_ILDemo
  6. {
  7. /// <summary>
  8. /// 装箱拆箱
  9. /// </summary>
  10. class Demo14_BoxUnBox
  11. {
  12. static string binaryName = "Demo14_BoxUnBox.exe";
  13. static string namespaceName = "LX1_ILDemo";
  14. static string typeName = "BoxUnBox";
  15.  
  16. static AssemblyBuilder assemblyBuilder;
  17. static ModuleBuilder moduleBuilder;
  18. static TypeBuilder typeBuilder;
  19. static MethodBuilder mainMethod;
  20. static ILGenerator ilGenerator;
  21.  
  22. static void Emit_Codes()
  23. {
  24. LocalBuilder loca1 = ilGenerator.DeclareLocal(typeof(object));
  25. LocalBuilder loca2 = ilGenerator.DeclareLocal(typeof(int));
  26.  
  27. LocalBuilder loca3 = ilGenerator.DeclareLocal(typeof(object));
  28. LocalBuilder loca4 = ilGenerator.DeclareLocal(typeof(double));
  29.  
  30. ilGenerator.Emit(OpCodes.Ldc_I4, int.MaxValue);
  31. ilGenerator.Emit(OpCodes.Box,typeof(int));
  32. ilGenerator.Emit(OpCodes.Stloc_0);
  33. ilGenerator.Emit(OpCodes.Ldloc_0);
  34. ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }));
  35. ilGenerator.Emit(OpCodes.Ldloc_0);
  36. ilGenerator.Emit(OpCodes.Unbox_Any, typeof(int));
  37. ilGenerator.Emit(OpCodes.Stloc_1);
  38. ilGenerator.Emit(OpCodes.Ldloc_1);
  39. ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }));
  40.  
  41. ilGenerator.Emit(OpCodes.Ldc_R8, double.MaxValue);
  42. ilGenerator.Emit(OpCodes.Box, typeof(double));
  43. ilGenerator.Emit(OpCodes.Stloc_2);
  44. ilGenerator.Emit(OpCodes.Ldloc_2);
  45. ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }));
  46. ilGenerator.Emit(OpCodes.Ldloc_2);
  47. ilGenerator.Emit(OpCodes.Unbox_Any, typeof(double));
  48. ilGenerator.Emit(OpCodes.Stloc_3);
  49. ilGenerator.Emit(OpCodes.Ldloc_3);
  50. ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(double) }));
  51. }
  52.  
  53. public static void Generate()
  54. {
  55. InitAssembly();
  56.  
  57. typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);
  58.  
  59. /* 生成 public static void Main() */
  60. GenerateMain();
  61.  
  62. Emit_Codes();
  63.  
  64. EmitReadKey();
  65. ilGenerator.Emit(OpCodes.Ret);
  66.  
  67. /* 设置assembly入口方法 */
  68. assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
  69.  
  70. SaveAssembly();
  71. Console.WriteLine("生成成功");
  72. }
  73.  
  74. static void EmitReadKey()
  75. {
  76. /* 生成 Console.ReadKey(); */
  77. MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
  78. ilGenerator.Emit(OpCodes.Call, readKeyMethod);
  79. ilGenerator.Emit(OpCodes.Pop);
  80. }
  81.  
  82. static void GenerateMain()
  83. {
  84. mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
  85. | MethodAttributes.Static, typeof(void), new Type[] { });
  86. ilGenerator = mainMethod.GetILGenerator();
  87. }
  88.  
  89. static void InitAssembly()
  90. {
  91. AssemblyName assemblyName = new AssemblyName(namespaceName);
  92. assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
  93. moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
  94. }
  95.  
  96. static void SaveAssembly()
  97. {
  98. Type t = typeBuilder.CreateType(); //完成Type,这是必须的
  99. assemblyBuilder.Save(binaryName);
  100. }
  101. }
  102. }

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. R语言︱SNA-社会关系网络 R语言实现专题(基础篇)(一)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:这里所有的应用代码都来自与igrap ...

  2. php出现Can't use function return value in write context

    <?php if(session('uid')){ }else{ } ?> 在用empty判断值为空的时候,报了这个Can't use function return value in w ...

  3. 《实战Nginx》读书笔记--Nginx配置文件

    先看下一份的Nginx 的配置 #user nobody nobody;#使用的用户和组 worker_processes 4;#工作进程的个数,一般等于CPU核数或者总核数的两倍 #error_lo ...

  4. VxWorks6.6 pcPentium BSP 使用说明(三):设备驱动

      本文主要介绍了pcPentium BSP中包含的驱动程序.包含了官方提供的所有驱动程序,除了aic7888Lib--现在已用得很少的一个AIC-7888 SCSI控制器的驱动介绍.建议重点阅读at ...

  5. Linux显示inode的信息

    Linux显示inode的信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ df -i 文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点 ...

  6. RHCE6.4 rpm 安装gcc

    先将gcc的iso里的Packages拷贝到根目录下,方便以后使用,再找gcc的rpm包安装: 网上说有以下依赖,需要按照一下顺序安装: rpm -ivh cpp*****.rpm  rpm -ivh ...

  7. Linux系统 awk sed R脚本 python脚本传入变量

    sed 传入变量: chrI="chr2";sed -n "/$chrI/p" clippointpos.csv  #变量用$var表示,把sed的单引号变为双 ...

  8. AJAX跨域问题总结

    跨域是什么? 首先说下同源,同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同.而跨域就是不同源 ! 能够进行跨域的请求 一般a,img,link[rel=stylesheet], ...

  9. 【转】MySQL乐观锁在分布式场景下的实践

    背景 在电商购物的场景下,当我们点击购物时,后端服务就会对相应的商品进行减库存操作.在单实例部署的情况,我们可以简单地使用JVM提供的锁机制对减库存操作进行加锁,防止多个用户同时点击购买后导致的库存不 ...

  10. 深度学习——卷积神经网络 的经典网络(LeNet-5、AlexNet、ZFNet、VGG-16、GoogLeNet、ResNet)

    一.CNN卷积神经网络的经典网络综述 下面图片参照博客:http://blog.csdn.net/cyh_24/article/details/51440344 二.LeNet-5网络 输入尺寸:32 ...