问题重现
下面直接给出用于说明文章主题的完整代码。
//************************************************************ // // Linq扩展方法示例代码 // // Author:三五月儿 // // Date:2014/10/01 // // http://blog.csdn.net/yl2isoft // //************************************************************ using System; using System.Collections.Generic; using System.Linq; namespace LinqExtendFunctionExp { class Program { static void Main(string[] args) { List<Student> studentList = new List<Student>(); studentList.Add(new Student() { Id = 1, Name = "ZhangSan", ClassId = 1, Score = 85}); studentList.Add(new Student() { Id = 2, Name = "LiSi" , ClassId = 2, Score = 76}); studentList.Add(new Student() { Id = 3, Name = "WangWu" , ClassId = 1, Score = 89}); studentList.Add(new Student() { Id = 4, Name = "ZhaoLiu", ClassId = 2, Score = 91 }); studentList.Add(new Student() { Id = 5, Name = "LiuJian" , ClassId = 1, Score = 78}); studentList.Add(new Student() { Id = 6, Name = "WuBin", ClassId = 2, Score = 67 }); var handledStudentList = studentList.GroupBy(it => it.ClassId).OrderBy(it => it.Max(p => p.Score)).ToList(); foreach (var students in handledStudentList) { foreach(var student in students) { if (student.Score < 85) { student.Name = "不合格"; } } } foreach (var s in studentList) { Console.WriteLine("Id = {0}, Name = {1}, ClassId = {2}, Score = {3}", s.Id, s.Name, s.ClassId, s.Score); } } } public class Student { public int Id { get; set; } public string Name { get; set; } public int ClassId { get; set; } public int Score { get; set; } } }
代码主要完成的工作是:
(1)定义学生对象集合studentList;
(2)使用Linq扩展方法对studentList集合进行分组和排序操作得到集合handledStudentList;
(3)遍历handledStudentList集合中的学生对象,当学生的成绩低于85时,修改该学生的姓名为“不合格”;
(4)输出studentList集合中所有学生的信息。
本文需要探讨的问题是:
在操作(4)中输出studentList集合学生信息时,Id为2,5,6的学生成绩低于85分,那么这些学生的姓名会被显示成“不合格”吗?
你可能会说不会,同时给出你的原因:
因为将学生姓名修改为“不合格”的操作是在遍历handledStudentList集合时完成的,因此修改的是handledStudentList集合中的学生信息,所以输出studentList集合中学生信息时不会受此影响。
但是,实际情况会是这样吗?请看代码的执行结果。
图1 代码运行结果
从图1可以了解到:学号为2,5,6的学生姓名被修改为了“不合格”,原因出在哪里呢?
问题分析
下面以扩展方法GroupBy为例来对问题进行分析,使用Linq中其他扩展方法的情况与使用扩展方法GroupBy的情况类似。
扩展方法GroupBy的作用是:按照指定的条件对集合进行分组操作,返回一个GroupedEnumerable类型的对象,在返回的对象内部仍然持有被分组集合的引用,所以,当我们操作分组后的集合时其实操作的仍然是分组前的集合对象。正因为此,才出现了本文前面描述的现象。
对于这点,是不是很容易被忽视啊,因为明明返回了一个新类型的对象,谁会想到,在它内部还持有被处理集合的引用呢。
好吧,希望大家在以后使用Linq的扩展方法时能注意这点。
至于GroupBy方法为什么会这样实现,那就得去研究GroupBy方法的源码了,等到以后有时间再说吧,这里只是想提出这样一个问题供大家参考,以免因为不知道这个知识点而出现一些本不应该出现的小问题。
好了,88。