加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如果lambda中的语句用于整个查询

发布时间:2020-12-16 00:18:28 所属栏目:百科 来源:网络整理
导读:这个陈述可以写成1个lambda表达式吗? if (filter.SubFormId.HasValue){ query = query.Where(c = c.SubFormId == filter.SubFormId);} 解决方法 对这种查询要非常小心. where子句绑定到变量过滤器,而不是当前值. 原始代码: var query = from form in forms
这个陈述可以写成1个lambda表达式吗?

if (filter.SubFormId.HasValue)
{
    query = query.Where(c => c.SubFormId == filter.SubFormId);
}

解决方法

对这种查询要非常小心. where子句绑定到变量过滤器,而不是当前值.

原始代码:

var query = from form in forms select form;
var filter = new Filter();
filter.SubFormId = 123;
if (filter.SubFormId.HasValue)
{
    query = query.Where(c => c.SubFormId == filter.SubFormId);
}
filter = null;
foreach(var matchingForm in query)
{ ... }

那段代码崩溃了.查询使用filter的当前值,而不是查询时的值.

Jared的版本并没有更好:

var query = from form in forms select form;
var filter = new Filter();
filter.SubFormId = 123;
query = query.Where(c => 
  !filter.SubFormId.HasValue || c.SubFormId == filter.SubFormId);
filter = null;
foreach(var matchingForm in query)
{ ... }

那也崩溃了.

如果过滤器以其他方式变异,那么您的版本和Jared的版本也会有不同的语义:

原始代码:

var query = from form in forms select form;
var filter = new Filter();
filter.SubFormId = null;
if (filter.SubFormId.HasValue)
{
    query = query.Where(c => c.SubFormId == filter.SubFormId);
}
filter.SubFormId = 123;
foreach(var matchingForm in query)
{ ... }

这符合每一种形式.你从未添加过Where子句.

Jared的版本做了不同的事情:

var query = from form in forms select form;
var filter = new Filter();
filter.SubFormId = null;
query = query.Where(c => 
  !filter.SubFormId.HasValue || c.SubFormId == filter.SubFormId);
filter.SubFormId = 123;
foreach(var matchingForm in query)
{ ... }

这只匹配subformId等于123的表单.Jared的版本与过滤子表单Id的当前值匹配(如果有的话),无论是否在构建查询时都存在.

请记住,查询是表示查询的对象.执行查询时,将从头开始重新执行查询,并根据查询关闭的变量的当前值来评估查询中的子句,而不是根据查询中存在的变量值的快照进行评估.创建了.查询具有实时,最新的变量视图.

So lets say I also return this query,which allows the query to be evaluated outside of the method. Would this crash since the filter will go out of scope?

简短回答:

没有.

更长的回答:

这是这个问题的重复:

Action/Lambda Expression Memory Management Question

详情请见我的回答.

答案很长:

您将范围与生命周期混淆 – 这是一个常见错误.范围纯粹是编译时的概念;局部变量的范围是程序文本的区域,其中该变量可以通过其名称引用.变量的生命周期纯粹是运行时概念;局部变量的生存期是垃圾收集器知道存储有效的时间段.

范围和寿命经常相关;虽然控制在逻辑上是在本地范围内的程序文本的一部分中,但是已知它是活着的.查询,lambda,迭代器块和异步块中使用的本地生命周期延长,因此即使控制离开本地范围,本地仍然存在.本地保持活着至少直到查询,lambda等已经死亡.

不幸的是,在某些情况下,当地居住的时间更长;请参阅上面的链接问题以获取示例.有关此问题的扩展讨论,请参阅此问题:

C# Action,Closure,and Garbage Collection

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读