呃,先不要砸鸡蛋。我说的Lambda表达式指的是Expression<T>,不是随便哪个item => { ... }。好吧,如果你还是不明白,那么我给你一个例子:
(抱歉,原来的return item;是个笔误,现已更正为 return (item%2) == 0;
int last = 0 ;
var query = values.Where(
item => {
last = item;
Console.WriteLine( " Last value ={0} " , last);
return (item%2) == 0;
}
);
var result = query.ToArray();
只要你在C# 4.0及以下版本跑,都会编译不通过。想知道编译器提示什么,请自己动手做实验。
(补充说明,我知道3.5里面没有BlockExpression等, 这些事Fx 4.0里面才加上的,我的意思是,为啥C# 4.0没有同步增加语法支持。有人说可能是没赶上,这个有点靠谱,不过到目前为止,我还是没有看到URL。希望知道的,手握资料的能贴出来分享一下。)
好了,问题来了:为什么不支持呢?这个问题暂时我没有找到什么答案,也许你能提供标准的答案。当然,我也有一些猜测:
1、和 item => item 这样的语法可能会有点冲突,不过也很好解决:只要限制statement都必须使用花括号即可;
2、可能有些QueryProvider无法支持执行语句,比如EntityFramework里面的ObjectQuery等。 不过我也没有觉得有什么太大问题,抛异常就好了。当然,这确实可能造成一些代码编译通过,但是执行的时候抛异常,你还不知道这样的查询是哪里构造出来的。就算是这样,那也只要尽早检查就能避免有问题的语句带病走太远。
不知道F#是否支持Lambda表达式中包含语句的情况,如果支持我都要想想是否转一个语言了,因为这对某些扩展造成了很大的困扰。比如说我本来构想是这样的:
(下面这部分代码又写错了,原来是CategoryId == XXX,少了 item. )
where item.CategoryId == 1
select item;
IQueryable < int > updateAffactedLine = query.Update(
item => {
item.CategoryId = GetCategoryId(NewCategoryDropDownList);
item.LastModifyDate = DateTime.Now;
}
);
嗯,你也许会说,这怎么可能执行呢?呃,好吧,如果你不了解表达式Expression这个东西,也不了解表达式访问器ExpressionVisitor这个东西,赶紧关了这个帖子。如果你懂的话,我这么说一下你大概就明白了:
1、执行之前需要估值,比如自己写一个类似.NET 类库里面的Norminator、PartialEvaluator(参见EnumerableQuery里面的方法),这样就可以计算类似GetCategoryId(NewCategoryDropDownList)这样的表达式的实际值,变成一个ConstantExpression;
2、在经过估值之后,自己写一个Provider(或者用别的方法),将这个表达式树转换成以下Sql语句:
update Photo set CategoryId = @P0, LastModifyDate = @P1 where CategoryId = 1
现在因为C#不支持这样的语法,只能用一个很Ugly的写法:
(补充,有人说不丑啊,比之前给出的方案没有多出几个字符。问题是,丑不丑不仅仅是你鼻子长了多少个的问题,地方不对照样很丑。这里面的丑在于,代码的表面含义是“产生一个新对象,并初始化某些属性”,但实际上并非这个含义,而是修改一些已有对象的某几个属性。“一个”和“一些”,“新对象”和“修改”都是不吻合的地方,我认为这就是丑。)
where item.CategoryId == 1
select item;
IQueryable < int > updateAffactedLine = query.UpdateUgly(
() => new Page(){
CategoryId = GetCategoryId(NewCategoryDropDownList),
LastModifyDate = DateTime.Now,
}
);
上面那个写法Ugly就算了,有些时候有的问题还是解决不了,比如……算了,我觉得再说就太深了,你们会晕掉的。我们还是把本贴的焦点拉回来:
该死的C#为啥不支持Expression<T>中带语句的语法?大家热烈讨论一下吧。(为什么说不解决问题,我在后面的回复中会提到,不过深了我还不打算这里说清楚,这不是一句两句话就能说清楚的。)
(嗯,我每次想到这就烦,它阻碍了我的一些设计,不得不搞得很Ugly。然后接着就会想到,总有人对语言的优美视为XX,甚至喜欢把这些问题和Execution performance混到一块说……哦哦,又扯远了。)
(补充:事实就是如此,又有人来说Execution performance的事情了,问题是我这里压根没打算探讨这个问题。)