MSIL实用指南-装箱拆箱
本篇讲述怎样装箱拆箱。装箱和拆箱都是针对值类型而言的,装箱的性能开销远比拆箱的性能开销大。
装箱
装箱指令是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 = 2147483647; 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); } } }