当前位置:主页   - 电脑 - 网站开发 - ASP.Net
Emit学习-基础篇-使用循环
来源:网络   作者:   更新时间:2012-03-26
收藏此页】    【字号    】    【打印】    【关闭

  本文示例源代码或素材下载

  今天我们来研究下用IL书写For循环和Foreach循环,在书中一直看到说使用Foreach循环比普通的For循环来的好,这次正好趁机来看看他们的IL代码有何不同.按照惯例,我们先给出要实现的类的C#代码,如下:

class Iterator
{
    public int ForMethod(int[] ints)
    {
        int sum = 0;
        for (int i = 0; i < ints.Length; i++)
        {
            sum += ints[i];
        }
        return sum;
    }

    public int ForeachMethod(int[] ints)
    {
        int sum = 0;
        foreach (int i in ints)
        {
            sum += i;
        }
        return sum;
    }
}

  然后,我们先来实现其中的ForMethod,相信大家已经等不及了,那么我先给出实现的IL代码,然后针对其中的关键部分进行讲解,代码如下:

  MakeForMethod

/// <summary>
/// 生成For循环
/// </summary>
/// <param name="typeBuilder"></param>
static void MakeForMethod(TypeBuilder typeBuilder)
{
    //定义一个传入参数为Int32[],返回值为Int32的方法
    MethodBuilder methodBuilder = typeBuilder.DefineMethod("ForMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(Int32), new Type[] { typeof(Int32[]) });
    ILGenerator methodIL = methodBuilder.GetILGenerator();

    //用来保存求和结果的局部变量
    LocalBuilder sum = methodIL.DeclareLocal(typeof(Int32));
    //循环中使用的局部变量
    LocalBuilder i = methodIL.DeclareLocal(typeof(Int32));

    Label compareLabel = methodIL.DefineLabel();
    Label enterLoopLabel = methodIL.DefineLabel();

    //int sum = 0;
    methodIL.Emit(OpCodes.Ldc_I4_0);
    methodIL.Emit(OpCodes.Stloc_0);
    //int i = 0
    methodIL.Emit(OpCodes.Ldc_I4_0);
    methodIL.Emit(OpCodes.Stloc_1);
    methodIL.Emit(OpCodes.Br, compareLabel);

    //定义一个标签,表示从下面开始进入循环体
    methodIL.MarkLabel(enterLoopLabel);
    //sum += ints[i];
    //其中Ldelem_I4用来加载一个数组中的Int32类型的元素
    methodIL.Emit(OpCodes.Ldloc_0);
    methodIL.Emit(OpCodes.Ldarg_0);
    methodIL.Emit(OpCodes.Ldloc_1);
    methodIL.Emit(OpCodes.Ldelem_I4);
    methodIL.Emit(OpCodes.Add);
    methodIL.Emit(OpCodes.Stloc_0);

    //i++
    methodIL.Emit(OpCodes.Ldloc_1);
    methodIL.Emit(OpCodes.Ldc_I4_1);
    methodIL.Emit(OpCodes.Add);
    methodIL.Emit(OpCodes.Stloc_1);

    //定义一个标签,表示从下面开始进入循环的比较
    methodIL.MarkLabel(compareLabel);
    //i < ints.Length
    methodIL.Emit(OpCodes.Ldloc_1);
    methodIL.Emit(OpCodes.Ldarg_0);
    methodIL.Emit(OpCodes.Ldlen);
    methodIL.Emit(OpCodes.Conv_I4);
    methodIL.Emit(OpCodes.Clt);
    methodIL.Emit(OpCodes.Brtrue_S, enterLoopLabel);

    //return sum;
    methodIL.Emit(OpCodes.Ldloc_0);
    methodIL.Emit(OpCodes.Ret);
}

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明