.NET, Architecture, ALM, Cloud

Publicité

Foreach Expression Trees

C# Code : 

 

Func<int, List<int>> foreachSample = (a) =>

                {

                    List<int> myList = new List<int>();

                    IEnumerable<int> numbers = new int[] { 1, 2, 3, 4 };

                    foreach (int number in numbers)

                        myList.Add(number * 2);

 

                    return myList;

                };

 

Expression Trees Code : 

 

var aParam = Expression.Parameter(typeof(int), "a");

var myListVariable = Expression.Variable(typeof(List<int>), "myList");

var numbersVariable = Expression.Variable(typeof(IEnumerable<int>), "numbers");

var enumerator = Expression.Variable(typeof(IEnumerator<int>), "enumerator");

LabelTarget looplabel = Expression.Label("looplabel");

var assignenumerator =

    Expression.Assign(enumerator, Expression.Call(numbersVariable, typeof(IEnumerable<int>).GetMethod("GetEnumerator")));

MethodCallExpression movenext = Expression.Call(enumerator, typeof(IEnumerator).GetMethod("MoveNext"));

var currentelement = Expression.Variable(typeof(int), "i");

var callCurrent = Expression.Assign(currentelement, Expression.Property(enumerator, "Current"));

 

 

Expression<Func<int, List<int>>> expression =

    Expression.Lambda<Func<int, List<int>>>(

    //{

    Expression.Block(

        new[] { myListVariable, numbersVariable, enumerator, currentelement },

    //myList = new List<int>();

        Expression.Assign(myListVariable, Expression.New(typeof(List<int>))),

    //numbers = new int[] { 1, 2, 3, 4 };

        Expression.Assign(numbersVariable, Expression.Constant(new int[] { 1, 2, 3, 4 })),

        assignenumerator,

    //foreach (int number in numbers)

        Expression.Loop(

        Expression.IfThenElse(movenext,

    //myList.Add(number * 2);

        Expression.Call(myListVariable, typeof(List<int>).GetMethod("Add"),

           Expression.Multiply( callCurrent, aParam)),

        Expression.Break(looplabel)), looplabel),

    //return myList;

        myListVariable),

        aParam);

 

Expression Trees Debug View : 

 

.Lambda #Lambda1<System.Func`2[System.Int32,System.Collections.Generic.List`1[System.Int32]]>(System.Int32 $a) {
    .Block(
        System.Collections.Generic.List`1[System.Int32] $myList,
        System.Collections.Generic.IEnumerable`1[System.Int32] $numbers,
        System.Collections.Generic.IEnumerator`1[System.Int32] $enumerator,
        System.Int32 $i) {
        $myList = .New System.Collections.Generic.List`1[System.Int32]();
        $numbers = .Constant<System.Int32[]>(System.Int32[]);
        $enumerator = .Call $numbers.GetEnumerator();
        .Loop  {
            .If (
                .Call $enumerator.MoveNext()
            ) {
                .Call $myList.Add(($i = $enumerator.Current) * $a)
            } .Else {
                .Break looplabel { }
            }
        }
        .LabelTarget looplabel:;
        $myList
    }
}

 

IL Code:

 

//myList = new List<int>();
IL_0000: newobj 08000000 is not a MethodDesc

6000003

//Get Enumerator

IL_0005: stloc.0

IL_0006: ldarg.0

IL_0007: ldfld 4000004 (02374db8)

IL_000c: ldc.i4.0

IL_000d: ldelem.ref

IL_000e: castclass 2000005 ""

IL_0013: stloc.1

IL_0014: ldloc.1

IL_0015: callvirt 08000000 is not a MethodDesc

6000006

IL_001a: stloc.2
//foreach (int number in numbers)

IL_001b: ldloc.2

IL_001c: callvirt 6000007 System.Collections.IEnumerator.MoveNext()

IL_0021: brfalse IL_003b

//myList.Add(number * 2)

IL_0026: ldloc.0

IL_0027: ldloc.2

IL_0028: callvirt 08000000 is not a MethodDesc

6000008

IL_002d: dup

IL_002e: stloc.3

IL_002f: ldarg.1

IL_0030: mul

IL_0031: callvirt 08000000 is not a MethodDesc

6000009

IL_0036: br IL_0040

//break

IL_003b: br IL_0045

//Loop

IL_0040: br IL_001b

//return myList;

IL_0045: ldloc.0

IL_0046: ret

 

 

Publicité
Retour à l'accueil
Partager cet article
Repost0
Pour être informé des derniers articles, inscrivez vous :
Commenter cet article