今天 来讲讲Linq这个好用的东西吧
不过我不会着墨在他哪些方法怎么用(这个自己Google应该就可以了
而是从另外一个面向来聊聊
先上Code 今天就拿可怜的学生作为白老鼠吧
public enum Gender{ Male, Female,}public class Student{ public string LastName { get; set; } public string FirstName { get; set; } public int Age { get; set; } public Gender Gender { get; set; }}
接下来下个简单的查询
我想查年龄16岁且是女性的学生
static void Main(string[] args){ var students = new List<Student>(); var result = students .Where(student => student.Age == 16 && student.Gender == Gender.Female) .ToList();}
非常好~这么简单难不倒我~
但是通常真正实作上才不会让你写hardcode
所以会有个input 让你依照input去查询
我就写个class当作input进来的结果
public class QueryInput{ /// <summary> /// 如果是空字串就不列入查询条件 /// </summary> public string LastName { get; set; } /// <summary> /// 如果是空字串就不列入查询条件 /// </summary> public string FirstName { get; set; } /// <summary> /// 如果是空就不列入查询条件 /// </summary> public int? Age { get; set; } /// <summary> /// 如果是空就不列入查询条件 /// </summary> public Gender? Gender { get; set; }}
这种还算简单 会有更複杂的 例如 可能要年龄大于某个值是落在某个区间
不过这个就不是这次的重点 就不特别提了
好 现在的需求是 要依照input的参数来查询
所以我常常可以看到这种程式码
static void Main(string[] args){ var students = new List<Student>(); var queryInput = new QueryInput(); var result = students; if (string.IsNullOrWhiteSpace(queryInput.FirstName)) { result = result.Where(student => student.FirstName == queryInput.FirstName).ToList(); } if (string.IsNullOrWhiteSpace(queryInput.LastName)) { result = result.Where(student => student.LastName == queryInput.LastName).ToList(); } if (queryInput.Age.HasValue) { result = result.Where(student => student.Age == queryInput.Age).ToList(); } if (queryInput.Gender.HasValue) { result = result.Where(student => student.Gender == queryInput.Gender).ToList(); }}
嘛..就结果来说答案是对了
但Linq有个非常重要的特性就是 延迟查询(Deferred Execution
这是什么意思呢? 就是你设定查询语句时 并不会真的去执行
只有在"需要的时候"才会去完整执行你的查询语句
例如 ToList,ToArray Foreach, First, Count...等
所以照上面的写法 如果每个查询条件都有去下 总共会跑 4次迴圈
static void Main(string[] args){ var students = new List<Student>(); var queryInput = new QueryInput(); var query = students.AsEnumerable(); if (string.IsNullOrWhiteSpace(queryInput.FirstName)) { query = query.Where(student => student.FirstName == queryInput.FirstName); } if (string.IsNullOrWhiteSpace(queryInput.LastName)) { query = query.Where(student => student.LastName == queryInput.LastName); } if (queryInput.Age.HasValue) { query = query.Where(student => student.Age == queryInput.Age); } if (queryInput.Gender.HasValue) { query = query.Where(student => student.Gender == queryInput.Gender); } var result = query.ToList();}
像这样 中间段其实就只是在设定查询语句而已 真正查询会在最后一行才执行
也只会跑一次迴圈而已
另外因为延迟查询的特性 如果想知道Count
var result = query.ToList();var count = query.Count();//不要这样写!var count = result.Count();
因为如果再ToList一次 他会再次查询
我们可以写个範例来看看
static void Main(string[] args){ var datas = new List<int>() { 1,2,3,4,5}; var query = datas.Where(x => x % 2 == 0); datas.Clear(); datas.Add(8); var result = query.ToList();//8 datas.Clear(); var count = query.Count();//0}
现在应该对延迟查询有些概念了吧?
所以不要任意去使用ToList 先设定好查询方式 只有在需要的时候才去作查询!