終於看到了第11章,之前雖然也有看過,但沒有太仔細,在工作中也偶爾會使用,但不明白其中的原理,那現在就來講講LINQ,做一做書蟲~~
首先先了解下LINQ的三個要點:
序列是LINQ的基礎,在你看到一個查詢表達式的時候,應該要想到它所涉及的序列:一開始總是存在至少一個序列,且通常在中間過程會轉換成其他序列,也可能和其他序列連接在一起。
1 class Car 2 { 3 public string Owner { get; set; } 4 public double Mileage { get; set; } 5 } 6 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 var list = new List<Car> { 12 new Car() { Owner="a",Mileage=100}, 13 new Car() { Owner="b",Mileage=200}, 14 new Car() { Owner="c",Mileage=300}, 15 new Car() { Owner="d",Mileage=400}, 16 new Car() { Owner="e",Mileage=500}, 17 new Car() { Owner="f",Mileage=600} 18 }; 19 20 var result = from e in list 21 where e.Mileage > 200 22 select e; 23 24 result.ToList().ForEach(x => Console.WriteLine(x.Owner)); 25 26 Console.ReadKey(); 27 28 } 29 }
上述的表達式作用:從一個汽車序列中找到裡程大於200的車。下一句代碼使用Lambda表達式來打印篩選出來的車主名。
上述中的查詢表達式被創建的時候,不會立刻處理數據,也不會訪問原始的汽車序列,而是在內存中生成這個查詢的表現形式,這個特點叫延遲執行。如下,在result.ToList()執行時,才會開始對序列的操作。
select expression 格式的語句,稱為投影。
1 result.Where(e => e.Mileage > 200).Select(e => e);
查詢表達式會編譯器轉譯為上面的代碼,可以看到它們是由擴展方法和Lambda表達式組成。在任何時候,參數(大多情況)都是委托類型,編譯器將用Lambda表達式作為實參,並盡量找到具有合適簽名的方法。再來看下我們的表達式
1 var result = from e in list 2 where e.Mileage > 200 3 select e;
from、where、in、select為查詢表達式上下文關鍵字,e為范圍變量、list為數據源序列、select e為返回投影。再看一個返回投影的例子。
1 var result1 = from e in list 2 where e.Mileage > 200 3 select e.Owner;
這裡的select e.Owner,即返回每輛車主的名字,那麼result1的類型為IEnumerable<string>
1 class Bigtruck :Car 2 { 3 public double Volume { get; set; } 4 5 } 6 7 var list0 = new List<Car> { 8 new Car() { Owner="a",Mileage=100}, 9 new Bigtruck() { Owner="b",Mileage=200,Volume=100.1}, 10 new Bigtruck() { Owner="c",Mileage=300,Volume=100.2}, 11 new Bigtruck() { Owner="d",Mileage=400,Volume=100.3}, 12 new Bigtruck() { Owner="e",Mileage=500,Volume=100.4}, 13 new Bigtruck() { Owner="f",Mileage=600,Volume=100.5} 14 }; 15 16 var castList = list0.Cast<Car>(); 17 var oftypeList = list0.OfType<Bigtruck>(); 18 19 Console.WriteLine(castList.Count()); //6 20 Console.WriteLine(oftypeList.Count()); //5
使用Cast<T>()會把列表中元素轉換成T類型,遇到不能轉換的元素將報錯,而OfType<T>()會嘗試轉換每個元素到T類型,遇到不能轉換的元素則跳過。當顯式聲明使用范圍變量時,會在轉譯時調用Cast()方法。如
1 var result2 = from Car e in list 2 select e; 3 result2 = list.Cast<Car>().Select(e => e);
表達式會轉譯為第三行的代碼。
請斧正。