一个方法体执行完指令后,必须要完成调用并返回,这是要使用Ret指令。
Ret指令的详细解释是从当前方法返回,并将返回值(如果存在)从被调用方的计算堆栈推送到调用方的计算堆栈上。就是说如果计算堆栈上没有变量,则返回void类型;如果有,则返回这个栈的变量,并且这个方法的返回类型就是栈上变量的数据类型。

下面例子是返回一个整数类型

ilInstaceGenerator.Emit(OpCodes.Ldc_I4,int.MaxValue);
ilInstaceGenerator.Emit(OpCodes.Ret);

完整的程序如下:

using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
class Demo10_Ret
{
static string binaryName = "Demo10_Ret.exe";
static string namespaceName = "LX1_ILDemo";
static string typeName = "RetTest"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder;
static MethodBuilder mainMethod;
static MethodBuilder GetMaxValueMethod;
static ConstructorBuilder constructorBuilder; static void Emit_GetMaxValue()
{
GetMaxValueMethod = typeBuilder.DefineMethod("GetMaxValue", MethodAttributes.Public | MethodAttributes.Static,
typeof(int), new Type[] { });
ILGenerator ilInstaceGenerator = GetMaxValueMethod.GetILGenerator();
ilInstaceGenerator.Emit(OpCodes.Ldc_I4,int.MaxValue);
ilInstaceGenerator.Emit(OpCodes.Ret);
} public static void Generate()
{
InitAssembly();
typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);
constructorBuilder = typeBuilder.DefineDefaultConstructor( MethodAttributes.Public);
Emit_GetMaxValue();
EmitMain(); /* 设置assembly入口方法 */
assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
SaveAssembly();
Console.WriteLine("生成成功");
} static void EmitMain()
{
mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
| MethodAttributes.Static, typeof(void), new Type[] { });
ILGenerator mainILGenerator = mainMethod.GetILGenerator(); mainILGenerator.Emit(OpCodes.Call, GetMaxValueMethod);
mainILGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) })); MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
mainILGenerator.Emit(OpCodes.Call, readKeyMethod);
mainILGenerator.Emit(OpCodes.Pop);
mainILGenerator.Emit(OpCodes.Ret); } 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. MSIL实用指南-Action的生成和调用

    MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...

  2. MSIL实用指南-生成索引器

    MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...

  3. MSIL实用指南-创建字段

    本篇讲解怎么创建字段,主要是在修饰符的创建上. 创建字段的方法是TypeBuilder.DefineField,传入字段名称.字段类型.字段修饰符等参数,返回一个FieldBuilder对象.先看这一 ...

  4. MSIL实用指南-创建方法和定义参数

    本篇讲解实现创建方法.指定参数的名称.实现参数加out和ref修饰符.以及参数加默认值. 创建方法 创建方法用类TypeAttributes的 DefineMethod(string name, Me ...

  5. MSIL实用指南-生成属性

    本篇讲解怎么生成属性,包括get和set方法. 第一步,生成一个字段生成字段用TypeBuilder.DefineField方法.实例代码: FieldBuilder customerNameBldr ...

  6. MSIL实用指南-生成构造函数

    本篇讲解生成构造函数的一些知识,包括创建实例构造函数.静态构造函数.调用父类构造函数. 生成构造函数的方法生成构造函数的方法是TypeBuilder.DefineConstructor(MethodA ...

  7. MSIL实用指南-闭包的生成和调用

    闭包(Closure)是词法闭包(Lexical Closure)的简称.对闭包的具体定义有很多种说法,这些说法大体可以分为两类: 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭 ...

  8. MSIL实用指南-生成异常处理

    本篇讲解怎么生成异常.C# 异常处理时建立在四个关键词之上的:try.catch.finally 和 throw. 一.异常的抛出抛出异常在C#语言中要使用throw关键字,使用方法是throw &l ...

  9. MSIL实用指南-IL版hello world

    我们学习编程开始时,一般用输出"hello world"的一段程序. C#版的"hello world"是 using System; namespace L0 ...

随机推荐

  1. 用python输出菱形

    num = eval(input('请输入最多*所在行数:')) a = num b = num #上三角 for i in range(1,num+1): print((a-1) *' ', (2* ...

  2. CCNA笔记(一)

    R1#enable R1#configure terminal R1(config)#interface fastEthernet 0/0R1(config-if)#ip address 12.1.1 ...

  3. [nghttp2]压测工具,源码编译并进行deb打包过程

    编译环境:deepin 15.11桌面版 nghttp2下载地址:https://github.com/nghttp2/nghttp2 环境要求 emm只能在类Linux环境才能完整编译,想在Wind ...

  4. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(一)

    序言 : 在看过<自己实现编译器链接器>源码之后,最近在看<编译器设计>,但感觉伪代码还是有点太浮空.没有掌握的感觉,也因为内网几乎没有LR(1)语法分析器生成器的内容,于是我 ...

  5. Liunx查看后1000行的命令以及查看中间部分

    linux 如何显示一个文件的某几行(中间几行) [一]从第3000行开始,显示1000行.即显示3000~3999行 cat filename | tail -n +3000 | head -n 1 ...

  6. 大陆争霸[SDOI2010]带限制最短路

    只要你有无限个自爆机器人,你就能为所欲为 斯普林·布拉泽 [题目描述] 略 一句话题意: 杰森国有 \(N\) 个城市,由 \(M\) 条单向道 路连接.杰森国的首都是城市 \(N\).你只需摧毁杰森 ...

  7. 第一次亲密接触——二狗子初识 CDN

    二狗子是国内知名XXX大学的在校学生,作为一名编程爱好者,他利用业余时间搭建了一个网站,把平时的学习心得和技术分享全都 PO 在自己的网站上.渐渐地,二狗子的网站因为文章质量高,技术分享全面,受到了很 ...

  8. shell 提取文件名和目录名

    转自http://blog.csdn.net/universe_hao/article/details/52640321 shell 提取文件名和目录名 在写shell脚本中,经常会有需要对路径和文件 ...

  9. (十七)c#Winform自定义控件-基类窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  10. gunicorn 基础配置使用

    flask 自带的 web 服务器稳定性较差,只能用于测试.最近做的 web 项目,每次启动,需要敲一堆参数文件,今天学习了官方文档里关于配置的说明,记录一下. 创建一个 gunicorn.conf ...