.Net4 Expression Tree 入门(4): 求N以内的所有质数
前面已经介绍了.Net4 Expression Tree的分支与循环,是时候综合起来写一个稍微复杂一点的实例了。
求N以内的所有质数
一般的写法
static List<int> GetPrimes_SimpleMethod(int to) { var res = new List<int>(); for (int n = 2; n <= to; n++) { bool found = false; for (int d = 2; d <= Math.Sqrt(n); d++) { if (n % d == 0) { found = true; break; } } if (!found) res.Add(n); } return res; }
暂且不用考虑以上算法的时间复杂度、性能什么的,因为只是为了学习 Expression Tree 而已。之前都说过,Expression 里是没有For这些常用方法的,只有Loop,因此为了更方便构造 Expression Tree, 需要对上面代码稍微修改成没for的形式。
如
for (int n = 2; n <= to; n++) { // do sth… }
改成 while形式:
int n = 2; while (true) { if (!(n <= to)) break; // do sth… n++; }
求N以内的所有质数的“NoFor” 写法
【纯粹是为了更方便构造 Expression Tree,否则相信没人用while(true)这样写法】
static List<int> GetPrimes_NoFor(int to) { var res = new List<int>(); int n = 2; while (true) { if (!(n <= to)) break; bool found = false; int d = 2; while (true) { if (!(d <= Math.Sqrt(n))) break; if (n % d == 0) { found = true; break; } d++; } if (!found) res.Add(n); n++; } return res; }
上述代码与表达式的对比列表
|
原始代码 |
表达式 |
| var res = new List<int>(); |
Expression.Assign( res, Expression.New(typeof(List<int>)) ) |
| int n = 2; |
Expression.Assign( n, Expression.Constant(2) ) |
while (true) { if (!(n <= to)) break; |
Expression.Loop( Expression.Block( Expression.IfThen( Expression.Not( Expression.LessThanOrEqual( n, to ) ), Expression.Break(breakOuter) ) |
| Math.Sqrt(n) |
Expression.Call( null, typeof(Math).GetMethod("Sqrt"), Expression.Convert( n, typeof(double) ) ) |
| d++; |
Expression.PostIncrementAssign(d)
|
| res.Add(n); |
Expression.Call( res, typeof(List<int>).GetMethod("Add"), n ) |
最终构建表达式的代码很长,有兴趣的不妨自己试着写写,这里不贴上来,可以参考这篇外文 《STATEMENT TREES WITH LESS PAIN – FOLLOW-UP ON SYSTEM.LINQ.EXPRESSIONS V4.0》。
你是否也因为Expression 里没有for这个方法而感到不爽?一切循环都得改成loop这种形式?Expression构建是不是很麻烦罗嗦?为什么Expression一切方法皆是static的…等等。
如果改成下面这种形式会不会好点?
|
原始代码 |
表达式 |
| var res = new List<int>(); |
res.Assign(Expression.New(typeof(List<int>))) |
| int n = 2; |
n.Assign(2) |
| n ++; |
n.PostIncrementAssign() |
| for (int n = 2; n <= to; n++) |
Expression.For(n, n.Assign(2), n <= to, n.PostIncrementAssign()
|
| res.Add(n); | res.Method("Add", n) |
这样会不会更简洁?欢迎作进一步交流。我会在下一篇随笔里分析如何实现以上形式的写法。
转自: http://www.cnblogs.com/coolcode/archive/2010/05/26/dotNet4_Expression_Tree_Beginning_4_Primes.html

浙公网安备 33010602011771号