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

本文通过一个阶乘示例,详细介绍了如何使用ExpressionTree实现循环逻辑,并对比了传统C#循环语句与ExpressionTree循环的不同之处。
前言

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

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()
                    …,
                    
                )

为了确保跑出“死循环”,必须制定一个条件“跳出去”(如 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()  …)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值