首页 > 其他分享 >.NET Emit 入门教程:第六部分:IL 指令:8:详解 ILGenerator 指令方法:类型转换指令

.NET Emit 入门教程:第六部分:IL 指令:8:详解 ILGenerator 指令方法:类型转换指令

时间:2024-04-15 10:14:40浏览次数:27  
标签:类型转换 OpCodes 入门教程 指令 typeof Emit il

前言:

经过前面几篇的学习,我们了解到指令的大概分类,如:

参数加载指令,该加载指令以 Ld 开头,将参数加载到栈中,以便于后续执行操作命令。

参数存储指令,其指令以 St 开头,将栈中的数据,存储到指定的变量中,以方便后续使用。

创建实例指令,其指令以 New 开头,用于在运行时动态生成并初始化对象。

方法调用指令,该指令以 Call 开头,用于在运行时调用其它方法。

支条件指令,该指令通常以 Br、或 B、C 开头,用于在运行分支条件时跳转指令。

本篇介绍类型转换指令,该指令通常以 Cast、Conv 开头或box结尾,用于在运行时对类型进行转换。

类型转换指令介绍:

在.NET中,类型转换是一个常见的操作,它允许我们在不同的数据类型之间进行转换。ILGenerator 提供了一系列的指令来执行各种类型转换操作。这些指令可以分为三类:强制类型转换指令、隐式类型转换指令和数值类型转换指令。

  1. 强制类型转换指令:这些指令用于执行显式的类型转换操作,如果转换失败则会抛出异常。常见的强制类型转换指令包括 castclass 和 isinst 指令。

  2. 隐式类型转换指令:这些指令用于执行从引用类型到值类型或者从值类型到引用类型的转换,或者在值类型之间执行转换。unboxbox 指令是常见的隐式类型转换指令。

  3. 数值类型转换指令:这些指令用于执行不同数值类型之间的转换,比如将整数转换为浮点数,或者将浮点数转换为整数。conv 指令系列提供了这些功能。

通过这些类型转换指令,我们可以在 IL 级别执行各种类型转换操作,为动态生成的代码增加了灵活性和功能性。

接下来我们将详细介绍这些指令的用法和示例。

1、强制类型转换指令:

Castclass 指令:强制类型转换

示例代码:

MethodBuilder methodBuilder = tb.DefineMethod("ConvertTo", MethodAttributes.Public | MethodAttributes.Static, typeof(XmlEntity), new Type[] { typeof(object) });

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0 );
il.Emit(OpCodes.Castclass, typeof(XmlEntity));
         
il.Emit(OpCodes.Ret);     // 返回该值

对应代码:

Isinst 指令: as 类型转换

示例代码:

MethodBuilder methodBuilder = tb.DefineMethod("ConvertTo", MethodAttributes.Public | MethodAttributes.Static, typeof(XmlEntity), new Type[] { typeof(object) });
ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0 );
il.Emit(OpCodes.Isinst, typeof(XmlEntity));

il.Emit(OpCodes.Ret);     // 返回该值

对应代码:

2、隐式类型转换指令:

1、Box 指令:装箱

示例代码:

MethodBuilder methodBuilder = tb.DefineMethod("ConvertTo", MethodAttributes.Public | MethodAttributes.Static, typeof(object), new Type[] { typeof(int) });
ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Box, typeof(int));

il.Emit(OpCodes.Ret);     // 返回该值

对应代码:

2、Unbox_Any 指令:拆箱

示例代码:

MethodBuilder methodBuilder = tb.DefineMethod("ConvertTo", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(object) });

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Unbox_Any, typeof(int));

il.Emit(OpCodes.Ret);     // 返回该值

对应代码:

3、Unbox 指令:拆箱并返回指向值的引用地址 

对应代码:

 可以看出,返回的是引用,如果需要获取值,需要配置 Ldobj 指令:

来一个示例代码:

var dynamicMethod = new DynamicMethod("ConvertTo", typeof(int), new Type[] { typeof(object) }, typeof(AssMethodIL_Condition));

ILGenerator il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Unbox, typeof(int));
il.Emit(OpCodes.Ldobj, typeof(int));

il.Emit(OpCodes.Ret);     // 返回该值

var result = dynamicMethod.Invoke(null, new object[] { 11 });
Console.WriteLine(result);
Console.Read();

运行效果:

可以理解为:

Unbox_Any 指令 = Unbox 指令 + Ldobj 指令。 

3、数值类型转换指令:

在CIL(Common Intermediate Language)中,"conv"(convert)相关指令用于进行类型转换,将一个数据类型转换为另一个数据类型。这些指令通常用于在不同的数据类型之间进行显式转换。

以下是一些常用的"conv"相关指令及其功能:

  1. conv.i1: 将值转换为有符号 8 位整数类型(sbyte)。
  2. conv.i2: 将值转换为有符号 16 位整数类型(short)。
  3. conv.i4: 将值转换为有符号 32 位整数类型(int)。
  4. conv.i8: 将值转换为有符号 64 位整数类型(long)。
  5. conv.u1: 将值转换为无符号 8 位整数类型(byte)。
  6. conv.u2: 将值转换为无符号 16 位整数类型(ushort)。
  7. conv.u4: 将值转换为无符号 32 位整数类型(uint)。
  8. conv.u8: 将值转换为无符号 64 位整数类型(ulong)。
  9. conv.r4: 将值转换为单精度浮点数类型(float)。
  10. conv.r8: 将值转换为双精度浮点数类型(double)。

这些指令在IL代码中用于执行类型转换操作。下面是一个简单的示例,演示如何使用这些指令:

var dynamicMethod = new DynamicMethod("ConvertTo", typeof(float), new Type[] { typeof(int) }, typeof(AssMethodIL_Condition));
ILGenerator il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Conv_R4); il.Emit(OpCodes.Ret); // 返回该值 var result = dynamicMethod.Invoke(null, new object[] { 11 }); Console.WriteLine(result); Console.Read();

运行结果:

在 Emit 中,类型是需要精确转换的,如果不进行转换,你可能得到类似这样的结果:

总结:

在本教程的第六部分中,我们深入探讨了 ILGenerator 中的类型转换指令。

通过了解这些指令,你可以在动态生成的代码中执行各种类型转换操作,从而更好地控制程序的行为和数据流。

类型转换指令在 .NET 开发中非常有用,特别是在需要进行数据类型转换或操作时。

通过本教程,你应该已经了解了如何使用 ILGenerator 来生成这些转换指令,并且知道它们在 IL 代码中的具体用法和语法。

掌握 ILGenerator 中的类型转换指令将为你的动态代码生成带来更大的灵活性和效率。

继续学习并探索 ILGenerator 中其他功能和指令,以加深对 .NET 平台底层运行机制的理解,并提升自己在 .NET 开发领域的技能水平。

 

标签:类型转换,OpCodes,入门教程,指令,typeof,Emit,il
From: https://www.cnblogs.com/cyq1162/p/18133303

相关文章

  • C++,四种强制类型转换,static_cast,const_cast,dynamic_cast,reinterpret_cast
      #include<iostream>usingnamespacestd;structA{virtualvoidfunc(){cout<<"Afunc"<<endl;}};structB:publicA{voidfunc(){cout<<"Bfunc"<<endl;}};intmain(){c......
  • 索引定位使用案例-类型转换
    sqlselectcount(0)from(selectdistinctcc.*,to_char(a1.D_DEALDATE,'yyyy-MM-dd')D_DEALDATE,a1.C_DATA_IDF,trim(a1.C_FIELD7)ZQFL,trim(a1.C_FIELD8)C_FIELD8,t......
  • .NET Emit 入门教程:第六部分:IL 指令:7:详解 ILGenerator 指令方法:分支条件指令
    前言:经过前面几篇的学习,我们了解到指令的大概分类,如:参数加载指令,该加载指令以 Ld开头,将参数加载到栈中,以便于后续执行操作命令。参数存储指令,其指令以St开头,将栈中的数据,存储到指定的变量中,以方便后续使用。创建实例指令,其指令以New开头,用于在运行时动态生成并初始化对......
  • String类型转LPCTSTR -----理解C++中的字符串类型转换
    在看代码时,发现有时候会把string类型转换为LPCTSTR,刚开始不理解为什么要做这个转换,所以做了一些调查,现在记录如下是这样的,STRING是代表C++中的字符串string,而LPCTSTR代表的是Windows系统中的字符串类型。也就是说,这样转换的目的是为了把C++中的字符串string转换为Windows系......
  • Linux:hostname指令
    学习自:Linux命令-hostname—LZL在线工具1、用途显示和设置系统的主机名称。主机名称保存在环境变量HOSTNAME中。2、用法显示主机名:hostname[-vadfisy]重设主机名:hostname[-vadfisy][主机名]3、参数参数说明-vhostname的具体用法(相当于help模式)-a显示......
  • directive自定义指令把文案转html+输入功能
    文案: "甲方(贷款人):全称:$var<text_aasdrup06rc00>法定代表人/负责人:$var<text_k2s9cffkhls00>地址:$var<text_6356yvx7oag00>\n\n乙方(借款人):全称/姓名:(变量-姓名),身份证号码/统一社会信用代码:(变量-身份证)地址:$var<text_1g9bed61qp7k0>\n\n鉴于:\n\n甲方与乙方于 $var<date_3ld......
  • C 强制类型转换
    强制类型转换是把变量从一种类型转换为另一种数据类型。例如,如果您想存储一个long类型的值到一个简单的整型中,您需要把long类型强制转换为int类型。您可以使用强制类型转换运算符来把值显式地从一种类型转换为另一种类型,如下所示:(type_name)expression请看下面的......
  • 4-2 dockderfile指令使用
    dockderfile详解创建自定义的Docker镜像 一、目录 1.docker典型结构 2.指令介绍 3.创建docker镜像二、结构 DockerFile分为四部分组成:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。例如:#viDockerfile#第一行必须指令基于的基础镜像Fromubutu......
  • 黑客入门教程(非常详细),从零基础入门到精通,看完这一篇就够了
    前言笔者本人17年就读于一所普通的本科学校,20年6月在三年经验的时候顺利通过校招实习面试进入大厂,现就职于某大厂安全联合实验室。我为啥说自学黑客,一般人我还是劝你算了吧!因为我就是那个不一般的人。首先我谈下对黑客&网络安全的认知,其实最重要的是兴趣热爱,不同于......
  • C语言 08 类型转换
    一种类型的数据转换为另一种类型的数据,这种操作称为类型转换。类型转换分为自动类型转换和强制类型转换。自动类型转换比如现在希望将一个short类型的数据转换为int类型的数据:#include<stdio.h>intmain(){shorts=10;//直接将s的值传递给i即可,但是注意此......