close
文章出處
裝配腦袋的習題在這里:Expression Tree上手指南 (一)
不了解Expression Tree的同學可以去看下,很好,很強大。
1: -a
2: a + b * 2
我把這些問題都弄成了方法,分別是Question1,Question2,….QuestionX
第一題:-a
因為實在是太短了,我不明白是什么意思,姑且認為是做取反操作吧,也就是假如輸入是5,那么輸出是-5.
如果讓你寫lambda表達式,估計沒幾個人寫不出來吧:(a)=>{return –a;}
當然你可以簡短點:(a)=>{-a}
OK,看一看lambda表達式:(a)=>{return –a;},可以知道有一個參數a,輸出是-a。
參數是ParameterExpression.
所以Question1里面基本代碼是:
private static void Question1() { ParameterExpression expPara = Expression.Parameter(typeof(int), "a"); }
先聲明一個參數a。類型是int.
接著應該對參數求反。那么我們應該使用求反表達式了。
在Msdn 里面的ExpressionType 里面可以查到
當然在Expression里面你也可以找到下面的方法:
public static UnaryExpression Negate(Expression expression);
于是代碼可以修改為:
private static void Question1() { ParameterExpression expPara = Expression.Parameter(typeof(int), "a"); UnaryExpression expNegate = Expression.Negate(expPara); }
OK,剩下的就是生成lambda表達式了,
使用Expression.Lambda方法就可以生成了。lambda表達式最關鍵的是參數和body。
參數是(a).所以傳遞的是expPara.
body就是lambda表達式的主體,你可以認為是{}之間的代碼,在這里傳遞的是expNegate.
為什么要生成lambda表達式??
因為可以編譯lambda表達式生成委托。
private static void Question1() { int a = 5; ParameterExpression expPara = Expression.Parameter(typeof(int), "a"); UnaryExpression expNegate = Expression.Negate(expPara); LambdaExpression expLmd = Expression.Lambda(expNegate, expPara); }
有了lambdaExpression后,就可以編譯LambdaExpression了。
private static void Question1() { int a = 5; ParameterExpression expPara = Expression.Parameter(typeof(int), "a"); UnaryExpression expNegate = Expression.Negate(expPara); LambdaExpression expLmd = Expression.Lambda(expNegate, expPara); Console.WriteLine(expLmd.Compile().DynamicInvoke(a)); } 運行結果如下:
DynamicInvoke的方法簽名如下:
//動態調用(后期綁定)由當前委托所表示的方法。 [SecuritySafeCritical] public object DynamicInvoke(params object[] args);
DynamicInvoke是后期綁定,所以性能比較差。
因為我們知道編譯后的expLmd.的參數類型是int,結果是int.
所以我們可以將委托轉換為Func<int,int>的強類型的委托。
private static void Question1() { int a = 5; ParameterExpression expPara = Expression.Parameter(typeof(int), "a"); UnaryExpression expNegate = Expression.Negate(expPara); LambdaExpression expLmd = Expression.Lambda(expNegate, expPara); Console.WriteLine(expLmd.Compile().DynamicInvoke(a)); Func<int, int> funcQuestion1 = expLmd.Compile() as Func<int, int>; Console.WriteLine(funcQuestion1(a)); }
第二題:a + b * 2
第一步,如果你寫lambda表達式,你應該怎么寫??
(int a,int b)=>{return a+ b *2;}
好了,會寫lambda表達式,基本上你也應該會寫Expression了。
參數:int a,int b;
body:return a+b*2;
private static void Question2() { ParameterExpression expA = Expression.Parameter(typeof(int), "a"); ParameterExpression expB = Expression.Parameter(typeof(int), "b"); }
聲明兩個變量a,b類型是int.
接著要寫body了。
body是a+b*2.
在這里2是常量。首先想到的是查看ExpressionType,看看有沒有什么表達式代表的是常量,當然你可以找到ConstantExpression
于是代碼變成了:
private static void Question2() { ParameterExpression expA = Expression.Parameter(typeof(int), "a"); ParameterExpression expB = Expression.Parameter(typeof(int), "b"); ConstantExpression exp2 = Expression.Constant(2); }
接著用()來分隔下a+b*2.
()的意思是先執行什么,后執行什么。
結果如下 a + (b *2)
先執行b*2,然后將b*2的結果和a相加。
Expression expBody = Expression.Add(expA, Expression.MakeBinary(ExpressionType.Multiply, expB, exp2));
Expression.MakeBinary(ExpressionType.Multiply, expB, exp2))
將expB和exp2進行相乘操作。然后和expA做相加操作。生成的就是expBody了。
因為我們知道參數是(int,int), 結果是int
所以委托的類型是Func<int,int,int>
完整的代碼如下:
private static void Question2() { ParameterExpression expA = Expression.Parameter(typeof(int), "a"); ParameterExpression expB = Expression.Parameter(typeof(int), "b"); ConstantExpression exp2 = Expression.Constant(2); Expression expBody = Expression.Add(expA, Expression.MakeBinary( ExpressionType.Multiply, expB, exp2)); Expression<Func<int, int, int>> lmd = Expression.Lambda<Func<int, int, int>> (expBody, expA, expB); Console.WriteLine(lmd.Compile()(3, 2)); }
不含病毒。www.avast.com |
全站熱搜
留言列表