今天 來講講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 先設定好查詢方式 只有在需要的時候才去作查詢!