BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

闭包的副作用

| 作者 Jonathan Allen 关注 595 他的粉丝 ,译者 王正 关注 0 他的粉丝 发布于 2007年10月2日. 估计阅读时间: 2 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

闭包并不是新概念,在LINQ的使用中已经证明了它难以置信地实用。但是,在它使用时如果破坏了封装,确实会带来明显的副作用。当把两个似乎无关的功能放在一起使用,就会出现意料不到的结果。

闭包允许函数把它们的本地变量共享给定义在这些函数内部的匿名函数。这些匿名函数通常被称作lambda表达式,对于创建由LINQ暴露的强类型查询语句来说是必不可缺的。

Dustin Campbell在对LINQ的实验中,发现查询语句在执行的时候能够被改变。的确如此,通过修改用在闭包代码中的本地变量,用于while子句的功能也就被修改了。如果这是在查询语句执行的时候改变的话,那么相应的查询语句也会有对应的变化和结果。

Dustin使用这个技巧去创建一个仅仅返回不重复项目的查询语句。最初,where子句是"m.Name != filter"。每次当一个条目被返回,filter的值随着条目的值改变。在这种情况下,查询语句能够成功地创建一个不重复的列表。

然而,这个技巧也是及其脆弱的。在Dustin的例子中,列表必须在where子句调用前先排好序。如果不这样做,过滤操作会在所有条目被返回前触发,这样也就没有机会去改变查询语句的行为了。因为where和order by子句可以以任意次序先后出现,这个功能在LINQ中是支持的。

Dustin没有提到的是,这个情况不会出现在所有的LINQ Provider中。那些要把查询语句交给像LINQ to SQL这样外部语法引擎的Provider,就没有机会改变where子句了。如果采用并行LINQ(Parallel LINQ),情况会更糟,因为在多个线程运行的时候,任何对where子句的改变都会引发竞态条件(race condition)。

当然,正确的方法应该是只调用Disctinct()就可以了。尽管这些技巧在理论上很有意思,但它们肯定会引发一些微妙的bug,而且也很容易收到框架中变化的影响。

查看英文原文:The Dark Side of Closures

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT