首页 新闻 会员 周边

Linq 问题 ,List.Where 筛选后的结果Tolist 和不Tolist 差别问题。

1
悬赏园豆:30 [已解决问题] 解决于 2015-02-26 15:19

            List<Person> persons = new List<Person>() {
               new Person(){ ID=1,Name="bbb", Age=1},
               new Person() { ID = 1, Name = "aaaa", Age = 2 }
             };

            persons.Where(o =>
              {
                  if (o.Age == 1 && o.Name == "bbb")
                  {
                      o.Name += "HEHE";
                      return true;
                  }
                  else
                      return false;
              });
            //1 bbb 1
            //1 aaa 2

  persons.Where(o =>
              {
                  if (o.Age == 1 && o.Name == "bbb")
                  {
                      o.Name += "HEHE";
                      return true;
                  }
                  else
                      return false;
              }).Tolist();
            //--ToList()后
            //1 bbbHEHE 1
            //1 aaa 2

谁详细的说下,为什么会出现这种情况,不加tolist persons里面的名字没加HEHE,Tolist之后就加上了HEHE..好奇怪啊

嘿嘿果宝的主页 嘿嘿果宝 | 初学一级 | 园豆:32
提问于:2015-02-25 19:12
< >
分享
最佳答案
0

楼主的第一个结果是如何输出的?

如果仅仅是调用了Where方法后,在编译器中看persons变量值是不会变的,因为这个是延迟查询,你的那句属性赋值操作没有真正执行。

查考:https://msdn.microsoft.com/zh-cn/library/bb534803(v=vs.110).aspx

 

第二个查询调用ToList方法,查询被执行了,persons变量内容被改变。

查考:https://msdn.microsoft.com/zh-cn/library/bb342261(v=vs.110).aspx

理解延迟查询和直接查询请查考:https://msdn.microsoft.com/zh-cn/library/bb397906.aspx

再看下源代码:

 你的

o => {
                  if (o.Age == 1 && o.Name == "bbb")
                  {
                      o.Name += "HEHE";
                      return true;
                  }
                  else
                      return false;
          }

就是predicate,只是作为参数传过去了,没有立即执行。

请参考:http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,e73922753675387a

收获园豆:20
C#开发人员 | 初学一级 |园豆:181 | 2015-02-26 13:40

很全面谢谢,你是个很认真的人。

嘿嘿果宝 | 园豆:32 (初学一级) | 2015-02-26 15:17

第一个结果是我在编译器中查看的,被你说中了 嘿嘿

嘿嘿果宝 | 园豆:32 (初学一级) | 2015-02-26 15:18
其他回答(3)
0

1、ToList will create a new list, but because in this case Person is a reference type then the new list will contain references to the same objects as the original list.

2、so ....

 

For your first linq query, it is ok, but can not update value. if you want to update value, should be something like,

persons.Where(o => o.Age == 1 && o.Name == "bbb").ToList().ForEach(c=>c.Name+="HEHE");

 

收获园豆:5
爱编程的大叔 | 园豆:30839 (高人七级) | 2015-02-25 21:57

我可以这样理解你上面的代码吗,where之后筛选出来了我要的数据,然后再去foreach循环去修改+=Name,因为是引用类型,所以直接修改会改变本来的persons里面的对象的值.

支持(0) 反对(0) 嘿嘿果宝 | 园豆:32 (初学一级) | 2015-02-26 12:14

还有你这种where之后foreach 的效率和我写的lamda表达式的方式哪个更好一点呢, 我的代码是where的时候查了一遍后面就不用再foreach了。

支持(0) 反对(0) 嘿嘿果宝 | 园豆:32 (初学一级) | 2015-02-26 12:25

@伦敦总依恋雨点: 不可以在Where里面修改的,你这个写法太诡异了。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30839 (高人七级) | 2015-02-26 12:27
0

1楼正解。学习了

那年、仲夏 | 园豆:202 (菜鸟二级) | 2015-02-25 22:39
0

ToList之后,直接返回结果集,是定集。不ToList,那么返回的是表达式,如果persons在之后变化了,那么结果也会在变化后的persons中去筛选。

收获园豆:5
幻天芒 | 园豆:37175 (高人七级) | 2015-02-26 08:41
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册