以下代码的原意是想找出list中满足Name字段包含t, Remark字段包含mark的数据
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
Dictionary < string , string > forms = new Dictionary < string , string > ();
forms.Add( " Name " , " t " );
forms.Add( " Remark " , " mark " );
// 构造一些数据 理论上全部数据都应该满足上面的那个条件 (忽略大小写)
List < UserInformation > list = new List < UserInformation > () {
new UserInformation(){Name = " Test1 " , Remark = " Remark1 " },
new UserInformation(){Name = " Test2 " , Remark = " Remark2 " },
new UserInformation(){Name = " Test3 " , Remark = " Remark3 " },
};
var lambda = list.AsQueryable();
foreach ( string key in forms.Keys)
{
string val = forms[key];
if (key == " Name " )
lambda = lambda.Where(p => p.Name.Contains(val)); // 原意是 在条件是Name的时候 对Name字段做过滤
if (key == " Remark " )
lambda = lambda.Where(p => p.Remark.Contains(val)); // 原意是 在条件是Remark的时候 对Remark字段做过滤
}
var data = lambda.ToList(); // 大家可以注意到结果是0条
var data2 = list.AsQueryable().Where(p => p.Name.Contains(forms[ " Name " ])).Where(p => p.Remark.Contains(forms[ " Remark " ])).ToList(); // 这个的结果是3条
不过实际情况是data中间一条记录都没有
而hardcode算出来的data2中有3条记录
原因如下:
这个lambda表达式 Where(p=>p.Name.Contains(val)) , 实际上只是保留了一个指向函数外部的val的引用 , 他这个时候并没有把val的真实的值拷贝进来
真正去读取val值的时候是 lambda.ToList() 这个时候才真正执行lambda表达式取数据,过滤数据 ,也是这个时候才去读取val的值
而在foreach的第二次操作的时候 val的值被覆盖mark了 那么就造成了 原来的Where(p=>p.Name.Contains(val)) 变成了 Where(p=>p.Name.Contains("mark"))
注意那个值是mark而不是t
如果我们把三条数据的Name都改成markdafafafadsf 之类的值 那么再次计算data的数据就会变成三条, 大家可以自己弄一下试试,
作用域:
本来val是一个临时变量,他的生命周期应该在foreach结束以后就结束了
但是 由于他被闭包引用,那么val的生命周期延长到引用对象的生命周期(那个lambda不死....val也就会一直活着)