LINQ,語言集成查詢(Language Integrated Query),是在.NET Framework 3.5 中出現的技術。
借助於LINQ技術,我們可以使用一種類似SQL的語法來查詢任何形式的數據。從技術角度而言,LINQ定義了大約40個查詢操作符,如from, select, in, where, group by, orderby, … 使用這些操作符可以編寫查詢語句。
做軟件的,總想代碼要怎么樣才能更好地復用,要怎么樣才更利於擴展,要怎么樣更能以不變應萬變。就如同微軟框架所提供的API一樣,在一定程度上避免開發者重復造輪子。拿LINQ來說吧,.NET Framework3.5及之后的版本都已經封裝進去,供成千上百萬的開發者使用。同一套LINQ語法,它能支持LINQ TO OBJECCT、LINQ TO XML、LINQ TO DATABASE。復用、減少開發工作量及降低學習成本等好處都是不言而喻的。LINQ的學習很像SQL,所以有使用過SQL語句的話,感覺還是蠻熟悉的。
上手簡單是學習LINQ的一大好處,語法很像SQL語句的語法。而且學一種技術,可以當多種技術來使用。這是不是很像那種多功能刀,一刀在手,生活無憂。LINQ支持集合、XML、數據庫的查詢。寫代碼就像說話,多必失,所以呢,盡量優化自己的代碼。這不但有利於減少錯誤的發生,也有利於提高生產率、降低維護的成本。而使用LINQ也是奔着這個方向發展。
坦白說,我看到網上有很多LINQ方面的教程,知識面介紹都挺好。我只能是厚着臉皮,站在巨人的肩膀上馳騁。本文基本是源於博友08年的文章,感覺他寫的很好。雖然抄襲是很可恥的行為,但是回想大學能順利畢業,論文也是東抄一塊,西抄一塊。所以現在我是很“蛋定”了。我要響應魯老爺的拿來主義精神。
LINQ是一種查詢語言,所以呢,運用的場景當然也就是查詢羅。查哪些,包括LINQ TO OBJECCT、LINQ TO XML、LINQ TO DATABASE。可以說查詢的范圍很廣。每一種都可以出一系列的文章,我們這里主要還是講 LINQ TO OBJECCT。
來看看從集合中,我們是怎么來查詢需要的值。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LinqApplication { class People { /// <summary> /// 名字 /// </summary> public string FirstName { get; set; } /// <summary> /// 姓氏 /// </summary> public string LastName { get; set; } /// <summary> /// 國家 /// </summary> public string Country { get; set; } } class Program { static void Main(string[] args) { List<People> listPeople = new List<People>() { new People{FirstName="Peter",LastName="Zhang",Country="China"}, new People{FirstName="Alan",LastName="Guo",Country="Japan"}, new People{FirstName="Linda",LastName="Tang",Country="China"} }; List<People> result = new List<People>(); foreach (People p in listPeople) { if (p.Country == "China") { result.Add(p); } } foreach(People p in result) { Console.WriteLine("Your name is :" + p.FirstName + " " + p.LastName); } Console.ReadKey(); } } }
上面的方法可以說是最直接,最容易想到的方法。上面的實現怎么看也沒有覺得有什么好復用的,但是事實是怎么樣?就有牛人看出了名堂,善於歸納上面的問題就是判斷是跟不是的問題,就想到要去提出來,供以后復用。 當然復用之路也不是一蹴而就的,也是日積月累而成。所以我們也來看看過渡的過程。
/// <summary> /// 判斷是否存在 /// </summary> /// <param name="p">對象</param> public static bool IsExist(People p) { return p.Country == "China"; }
如果說只是如下方式來實現的話,那還真是白費力氣了。
foreach (People p in listPeople) { if (IsExist(p)) { result.Add(p); } }
但是結合到委托的話,我們就可以把IsExist(People p)當成一個參數來進行傳遞。這里我們過渡再快一點,我們把查詢的那一段代碼提到另一類Helper供以后得用。我們來看看Helper類的代碼實現。限於篇幅的問題,只截Helper類的方法。
public class Helper { //聲明委托 public delegate bool ExistPeople(People p); /// <summary> /// 獲取滿足條件的數據 /// </summary> /// <param name="listPeople">數據集</param> /// <param name="existPeople">條件</param> public static List<People> GetPeopleResult(IList<People> listPeople, ExistPeople existPeople) { List<People> result = new List<People>(); foreach (People p in listPeople) { if (existPeople(p)) { result.Add(p); } } return result; } }
這樣我們就可以直接調用,來獲取滿足條件的數據了。也可以使用C#2.0提供的匿名委托,還可以使用C#3.0的Lambda表述式。代碼如下:
static void Main(string[] args) { List<People> listPeople = new List<People>() { new People{FirstName="Peter",LastName="Zhang",Country="China"}, new People{FirstName="Alan",LastName="Guo",Country="Japan"}, new People{FirstName="Linda",LastName="Tang",Country="China"} }; IList<People> result = new List<People>(); //直接調用 result = Helper.GetPeopleResult(listPeople, IsExist); //匿名委托 //result = Helper.GetPeopleResult(listPeople, delegate(People p){ return p.Country == "China" ? true : false;}); //Lambda表達式 //result = Helper.GetPeopleResult(listPeople, people => people.Country == "China"); foreach(People p in result) { Console.WriteLine("Your name is :" + p.FirstName + " " + p.LastName); } Console.ReadKey(); }
講到這里,對於具體集合的查詢基本上是完成了,但是呢,C#3.0還提供了一種方法,使調用的代碼更加直觀,那就是擴展方法。通過擴展IList集合的方法,我們就可以通過IList來調用並傳遞委托條件即可。
Helper類的擴展代碼如下:
public static class Helper { //聲明委托 public delegate bool ExistPeople(People p); /// <summary> /// 獲取滿足條件的數據 /// </summary> /// <param name="listPeople">數據集</param> /// <param name="existPeople">條件</param> public static IList<People> GetPeopleResult(this IList<People> listPeople, ExistPeople existPeople) { List<People> result = new List<People>(); foreach (People p in listPeople) { if (existPeople(p)) { result.Add(p); } } return result; } }
我們看Main方法的調用,是不是很直觀了,就像調用集合的方法,並給傳遞委托條件即可了。Main方法如下:
static void Main(string[] args) { List<People> listPeople = new List<People>() { new People{FirstName="Peter",LastName="Zhang",Country="China"}, new People{FirstName="Alan",LastName="Guo",Country="Japan"}, new People{FirstName="Linda",LastName="Tang",Country="China"} }; IList<People> result = new List<People>(); //直接調用 //result = Helper.GetPeopleResult(listPeople, IsExist); //匿名委托 //result = Helper.GetPeopleResult(listPeople, delegate(People p){ return p.Country == "China";}); //Lambda表達式 //result = Helper.GetPeopleResult(listPeople, people => people.Country == "China"); //擴展方法調用 result = listPeople.GetPeopleResult(people => people.Country == "China"); foreach(People p in result) { Console.WriteLine("Your name is :" + p.FirstName + " " + p.LastName); } Console.ReadKey(); }
上面是使用GetPeopleResult方法名,但是我們想要的話,是不是就可以實現諸如Select、Where、OrderBy等方法了。基本上方法的介紹就已經完了。但是有一個大的問題,那就是它還比較死,不靈活,因為我們不可能說每個集合里面的對象(本文是People)都重復來寫。這里肯定是需要提供一種方式,使它能夠接受不同的對象,這樣才有利於我們復用。因為IList繼承自IEnumerable,所以可以給IEnumerable實現擴展方法,然后利用泛型的特征,就可以給不同的對象來復用,代碼如下:
public static class Helper { public delegate bool Condtion<T>(T t); public static IEnumerable<T> GetPeopleResult<T>(this IEnumerable<T> items, Condtion<T> condition) { foreach (T t in items) { if (condition(t)) { //C# 2.0里出現的一個關鍵字,返回一個迭代器 yield return t; } } } }
Main方法就不貼全部了,畢竟上面都重復好幾回,只貼調用那一句:
IEnumerable<People> result = Helper.GetPeopleResult<People>(listPeople, people => people.Country == "China");
而C# 3.0則給我們提供var關鍵字,被稱為推斷類型。
var 關鍵字能指示編譯器根據初始化語句右側的表達式推斷變量的類型。推斷類型可以是內置類型、匿名類型、用戶定義類型、.NET Framework 類庫中定義的類型或任何表達式。所以上面的式子可以寫成如下方式:
var result = Helper.GetPeopleResult<People>(listPeople, people => people.Country == "China");
到此本文就正式結束,站在前人的肩膀下感覺真好,很多成果就是可以拿來就用,樂哉樂哉!希望大伙一起好好學習,天天向上了。