.Net4 Expression Tree 入门(3): Loop 循环

前言

刚开始学习编程时,我认为程序带来的价值远不如我为它写的代码多,因为它顶多算加减乘除比一般人快而已,直到我认识了“循环”。而一天后,我又发现程序可以“死循环”,而当时我应付“死循环”的方法是——关机 (- . -!) 狂汗啊!

Loop 循环

这篇文章介绍 Expression Tree 的循环语句:For,Do,While。咳咳,应该是Loop!没错,Expreession Tree里没有For,Do,While这些熟悉的朋友,叫了他们的祖先Loop来应付。正如鲁迅那句经典的语录——世界上本没有For,Do,While,程序员写代码写多了烦了,也便有了。

实际上,Loop和Do差不多,它等价于

do{

if(不合适)

break;

}

以下语句可能会有助于你对上述伪代码的理解【未成年的童鞋直接跳到下一段】:不管三七二十一,先do了再说,如果性格不合适就分手。由此可以判断:Loop不是一个专一的家伙。

示例

现在举一个阶乘(如: n!=n*(n-1)*…*2*1)的例子来说明Expreession Tree是如何做循环的。

一般来说,用C#语法是这样写的:

int result = 1;
do
{
    result *= n;
    n--;
} while (n > 1);

 

为了更接近方便构建Expreession Tree,把以上语句改成伪代码格式:

int result = 1;
do
{
    if (n > 1)
    {
        result *= n;
        n--;
    }
    else
    {
        break;
    }
}

 

对应的表达式树构建:

ParameterExpression value = Expression.Parameter(typeof(int), "value");
ParameterExpression result = Expression.Parameter(typeof(int), "result");
LabelTarget label = Expression.Label(typeof(int));
BlockExpression block = Expression.Block(
    new[] { result },
    Expression.Assign(result, Expression.Constant(1)),
    Expression.Loop(
        Expression.IfThenElse(
            Expression.GreaterThan(value,
                Expression.Constant(1)),
            Expression.MultiplyAssign(result,
                Expression.PostDecrementAssign(value)),
        Expression.Break(label, result)
        ),
        label
    )
);
Expression<Func<int, int>> lambda = Expression.Lambda<Func<int, int>>(block, value);
Func<int, int> func = lambda.Compile();
Console.WriteLine(func(5));

 

一般来说,Expression Tree 的循环由Expression.Loop 、 Expression.Break 和 LabelTarget 共同构成,如下面格式:

Expression.Loop(
                    …
                    Expression.Break(label)
                    …,
                    label
                )

为了确保跑出“死循环”,必须制定一个条件“跳出去”(如 Break LabelTarget)。

另外, Expression.MultiplyAssign(result, Expression.PostDecrementAssign(value)) 所表达的就是result *= n--; 也就是 result *= n; n—;  合并成一个语句而已。

总结

值得思考 Expression 里为什么没有For这样常用的方法?

这里埋下伏笔,其实我很早就写好了For,在我自定义的FluentExpression里的写法大概是这样子,以后会详细介绍。

FluentExpression.For(n, n.Assign(2), n <= to, n.PostIncrementAssign()  …)


作者:Bruce编程的艺术世界
出处:http://coolcode.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted on 2010-05-17 00:29  CoolCode  阅读(2567)  评论(1编辑  收藏  举报