c#提供的ling查詢極大的遍歷了集合的查詢過程,且使用簡單方便,很是的有用。express
下面將分別用簡單的例子說明:ling基本查詢、延遲查詢屬性、類型篩選、複合from字句、多級排序、分組查詢、聯合查詢、合併、分頁、聚合操做符、並行linq、取消長時間運行的並行ling查詢。c#
Lambda表達式簡介:數組
/*Lambda表達式:Lambda 表達式是一種可用於建立委託或表達式目錄樹類型的匿名函數 表達式位於 => 運算符右側的 lambda 表達式稱爲「表達式 lambda」。 * (input parameters) => expression * 示例:*/ delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //最後j = 25 }
語句:dom
var query = from r in listStudents where r.score < 60 orderby r.score descending select r; //var q2 = listStudents.Where(r => r.score < 60).OrderByDescending(r => r.score).Select(r => r) ;//或使用Lambda表達式
例子:ide
/// <summary> /// 學生結構體 /// </summary> struct Student { /// <summary> /// 姓名 /// </summary> public string name; /// <summary> /// 年齡 /// </summary> public int age; /// <summary> /// 班號 /// </summary> public int grade; /// <summary> /// 分數 /// </summary> public float score; } /// <summary> /// linq /// 基本查詢 /// </summary> static void Linq1() { #region 構造查詢數據 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孫xxx"; break; case 4: name = "錢xxx"; break; default: name = "趙xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion //從50個學生中選擇出不及格的人員名單並按分數降序排列 var query = from r in listStudents where r.score < 60 orderby r.score descending select r; //var q2 = listStudents.Where(r => r.score < 60).OrderByDescending(r => r.score).Select(r => r) ;//或使用Lambda表達式 //orderby升序即從小到大,orderby r.score descending降序即從大到小 Console.WriteLine("不及格的人員名單:"); foreach (Student st in query) { Console.WriteLine("***************"); Console.WriteLine("姓名:"+st.name); Console.WriteLine("班級:"+st.grade); Console.WriteLine("年齡:"+st.age); Console.WriteLine("分數:"+st.score); } Console.ReadKey(); }
linq查詢爲延遲查詢,只需構造一次查詢語句,能夠屢次使用。函數
例子:spa
/// <summary> /// Linq /// 延遲查詢 /// linq查詢爲延遲查詢,只需構造一次查詢語句,能夠屢次使用 /// </summary> static void Linq2() { #region 構造查詢數據 List<string> lists = new List<string> { "Jack","Pet","Hant","Li","Kkk"}; #endregion var query = from r in lists where r.StartsWith("J") select r; Console.WriteLine("第一次查詢結果:"); foreach (string st in query) { Console.WriteLine( st); } Console.WriteLine("第二次查詢結果:"); lists.Add("Jone"); lists.Add("Jimi"); lists.Add("Johu"); foreach (string st in query) { Console.WriteLine(st); } Console.ReadKey(); /* 輸出結果: * 第一次:Jack * 第二次:Jack Jone Jimi Johu */ }
利用OfType方法能夠把特定類型數據篩選出來。線程
例子:3d
/// <summary> /// Linq類型篩選-ofType /// </summary> static void Linq3() { object[] pList = new object[] { 1,"one",2,"two",3,"three"}; var query = pList.OfType<string>(); foreach (var st in query) { Console.WriteLine(st); } Console.ReadKey(); /* 輸出結果: * one two three */ }
語句:code
var query = from s in listStudents from n in s.name where n == '趙' orderby s.score descending select s.grade + "班-" + s.name + ",分數" + +s.score; /*查詢出全部姓趙的學生的班級、姓名、分數信息,並按分數由高到低排序*/
例子:
/// <summary> /// linq複合from字句 /// </summary> static void Linq4() { #region 構造查詢數據 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孫xxx"; break; case 4: name = "錢xxx"; break; default: name = "趙xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion var query = from s in listStudents from n in s.name where n == '趙' orderby s.score descending select s.grade + "班-" + s.name + ",分數" + +s.score; /*查詢出全部姓趙的學生的班級、姓名、分數信息,並按分數由高到低排序*/ foreach (var t in query) { Console.WriteLine(t); } Console.ReadKey(); }
語句:
//參數越靠前,優先級越高 //先按score排序,當分數相同時再按grade排序...依次類推 var query = from s in listStudents orderby s.score, s.grade, s.age, s.name select s;
例子:
/// <summary> /// 多級排序 /// </summary> static void Linq5() { #region 構造查詢數據 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孫xxx"; break; case 4: name = "錢xxx"; break; default: name = "趙xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion //參數越靠前,優先級越高 //先按score排序,當分數相同時再按grade排序...依次類推 var query = from s in listStudents orderby s.score, s.grade, s.age, s.name select s; foreach (Student st in query) { Console.WriteLine("***************"); Console.WriteLine("姓名:" + st.name); Console.WriteLine("班級:" + st.grade); Console.WriteLine("年齡:" + st.age); Console.WriteLine("分數:" + st.score); } Console.ReadKey(); }
語句:
//按國家分組,並選出大於2的組,造成新的集合 var query = from r in listChampion group r by r.country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new { country = g.Key, count = g.Count() };
例子:
/// <summary> /// 分組 /// </summary> static void Linq6() { List<Champions> listChampion = new List<Champions>(); listChampion.Add(new Champions() { name = "張**", country = "中國" }); listChampion.Add(new Champions() { name = "趙**", country = "中國" }); listChampion.Add(new Champions() { name = "李**", country = "中國" }); listChampion.Add(new Champions() { name = "李**", country = "中國" }); listChampion.Add(new Champions() { name = "Peter", country = "美國" }); listChampion.Add(new Champions() { name = "Hune", country = "美國" }); listChampion.Add(new Champions() { name = "Hune", country = "美國" }); listChampion.Add(new Champions() { name = "Jack", country = "俄羅斯" }); listChampion.Add(new Champions() { name = "Jack", country = "俄羅斯" }); listChampion.Add(new Champions() { name = "Jimi", country = "英國" }); //按國家分組,並選出大於2的組,造成新的集合 var query = from r in listChampion group r by r.country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new { country = g.Key, count = g.Count() }; foreach (var o in query) { Console.WriteLine("國家:{0},冠軍數:{1}個", o.country, o.count); } Console.ReadKey(); }
語句:
//查詢出集合qSt中year等於集合qSc中year的元素並造成新的集合 var qjoin = from r in qSt join c in qSc on r.year equals c.year select new { Year = r.year, stName = r.name, scName = c.name };
例子:
/// <summary> /// 聯合查詢-join /// </summary> static void Linq7() { List<s> pSt = new List<s>(); pSt.Add(new s() {year=1999,name="xxx" }); pSt.Add(new s() { year = 2000, name = "xxx" }); pSt.Add(new s() { year = 2001, name = "xxx" }); pSt.Add(new s() { year = 2010, name = "xxx" }); List<school> pSc = new List<school>(); pSc.Add(new school() { year = 1999, name = "***" }); pSc.Add(new school() { year = 2001, name = "***" }); pSc.Add(new school() { year = 2002, name = "***" }); pSc.Add(new school() { year = 2010, name = "***" }); pSc.Add(new school() { year = 2012, name = "***" }); var qSt = from r in pSt where r.year >= 2000 select r; var qSc = from r in pSc where r.year >= 2000 select r; //查詢出集合qSt中year等於集合qSc中year的元素並造成新的集合 var qjoin = from r in qSt join c in qSc on r.year equals c.year select new { Year = r.year, stName = r.name, scName = c.name }; foreach (var ite in qjoin) { Console.WriteLine(ite.Year + " " + ite.scName + " " + ite.stName); Console.WriteLine(""); } Console.ReadKey(); }
.Net4.0新增,可對兩個相關的序列進行合併。
語句:
/*若合併兩項項數不一樣,則在達到較小集合的末尾時中止*/ var qZip = qSc.Zip(qSt, (first, second) =>string.Format("Year:{0},Name:{1}.", first.Year,second.Name));//返回值qZip爲字符串集合
例子:
/// <summary> /// 合併-zip()-.Net4.0新增,可對兩個相關的序列進行合併 /// </summary> static void Linq8() { List<s> pSt = new List<s>(); pSt.Add(new s() { year = 1999, name = "一xxx" }); pSt.Add(new s() { year = 2000, name = "二xxx" }); pSt.Add(new s() { year = 2001, name = "三xxx" }); pSt.Add(new s() { year = 2010, name = "四xxx" }); pSt.Add(new s() { year = 2010, name = "五xxx" }); List<school> pSc = new List<school>(); pSc.Add(new school() { year = 1999, name = "1***" }); pSc.Add(new school() { year = 2012, name = "2***" }); pSc.Add(new school() { year = 2012, name = "3***" }); pSc.Add(new school() { year = 2012, name = "4***" }); pSc.Add(new school() { year = 2012, name = "5***" }); var qSt = from r in pSt where r.year >= 2000 orderby r.year select new { Year = r.year, Name = r.name }; var qSc = from r in pSc where r.year >= 2000 orderby r.year select new { Year = r.year, Name = r.name }; /*若合併兩項項數不一樣,則在達到較小集合的末尾時中止*/ var qZip = qSc.Zip(qSt, (first, second) =>string.Format("Year:{0},Name:{1}.", first.Year,second.Name));//返回值qZip爲字符串集合 foreach (var ite in qZip) { Console.WriteLine(ite); } Console.ReadKey(); }
經過Take()和Skip()實現只顯示部分查詢結果。
語句:
//經過skip跳過指定數量的元素,再經過take提取固定長度元素,可實現分頁 var qr = (from r in listStudents orderby r.score descending select r).Skip(i * pageSize).Take(5); //var qr2 = listStudents.OrderByDescending(r => r.score).Select(r => r).Skip(i * pageSize).Take(5);//或
例子
/// <summary> /// 分區(分頁)-經過Take()和Skip()實現只顯示部分查詢結果 /// </summary> static void Linq9() { #region 構造查詢數據 List<Student> listStudents = new List<Student>(); Random pRandom = new Random(); for (int i = 1; i < 50; i++) { float sc = pRandom.Next(0, 100); int age = pRandom.Next(8, 13); int gde = pRandom.Next(1, 6); string name = ""; switch (pRandom.Next(0, 6)) { case 1: name = "周xxx"; break; case 2: name = "李xxx"; break; case 3: name = "孫xxx"; break; case 4: name = "錢xxx"; break; default: name = "趙xxx"; break; } Student psdt = new Student(); psdt.name = name; psdt.age = age; psdt.grade = gde; psdt.score = sc; listStudents.Add(psdt); } #endregion int pageSize = 5; int numofPage = (int)Math.Ceiling(listStudents.Count /(double)pageSize); for (int i = 0; i < numofPage; i++) { Console.WriteLine("第{0}頁", i); //經過skip跳過指定數量的元素,再經過take提取固定長度元素,可實現分頁 var qr = (from r in listStudents orderby r.score descending select r).Skip(i * pageSize).Take(5); //var qr2 = listStudents.OrderByDescending(r => r.score).Select(r => r).Skip(i * pageSize).Take(5);//或 foreach (var ite in qr) { Console.WriteLine(ite.name); Console.WriteLine(ite.score); } Console.WriteLine(""); } Console.ReadKey(); }
並行查詢能夠分解查詢的工做,使其分佈在多個線程上。當pc擁有多個cpu時,能夠看到並行查詢帶來的改進效果。並行LINQ適用於大型的集合查詢,並擁有必定的優點。使用
System.Collections.Concurrent.Partitioner.Create
能夠手動建立分區器。
語法:
var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//並行查詢 //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或並行查詢(Lambda表達式)
例子:
/// <summary> /// 並行linq /// </summary> static void Linq11() { Console.WriteLine("開始構造大數組..."); //構造大數組 const int count = 100000000; var data = new int[count]; var r = new Random(); for (int i = 0; i < count; i++) { data[i] = r.Next(40); } Console.WriteLine("開始計算..."); var st = System.DateTime.Now; var sum = (from x in data where x > 20 select x).Sum();//常規linq-耗時1.8641s var st2 = System.DateTime.Now; var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//並行查詢-耗時0.6620s //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或並行查詢----x3 => x3 > 20(Lambda表達式) var st3 = System.DateTime.Now; /*Partitioner.Create 手動建立分區器 * Create具備多個重載,可依據需求進行分區 */ var sum4 = (from c in System.Collections.Concurrent.Partitioner.Create(data, true).AsParallel() where c > 20 select c).Sum(); var dt1 = st2 - st; var dt2 = st3 - st2; Console.WriteLine("常規linq耗時:{0}s",dt1.TotalSeconds.ToString()); Console.WriteLine("並行linq耗時:{0}s", dt2.TotalSeconds.ToString()); Console.ReadKey(); }
輸出結果:
能夠粗魯的認爲並行linq對於大集合的查詢是優點比較明顯的。
對於並行ling而言,能夠設置能夠利用System.Threading.CancellationTokenSource設置取消操做。
語法:
//經過.WithCancellation(cts.Token)設置 var sum = (from x in data.AsParallel().WithCancellation(cts.Token) where x < 20 select x).Average();
例子:
/// <summary> /// 取消長時間運行的並行linq查詢 /// </summary> static void Linq12() { //構造大數組 const int count = 100000000; var data = new int[count]; var r = new Random(); for (int i = 0; i < count; i++) { data[i] = r.Next(40); } var cts = new System.Threading.CancellationTokenSource(); new System.Threading.Thread(() => { try { //經過.WithCancellation(cts.Token)設置 var sum = (from x in data.AsParallel().WithCancellation(cts.Token) where x < 20 select x).Average(); Console.WriteLine("sum:{0}", sum); } catch(OperationCanceledException ex) { Console.WriteLine(ex.Message); } }).Start(); Console.WriteLine("計算開始..."); Console.WriteLine("取消請按n!"); var rk = Console.Read(); if(rk=='n'||rk=='N') { cts.Cancel(); } }
至此,對於LINQ已經有了一個基本的瞭解。