C# LINQ查詢表達(dá)式及對(duì)應(yīng)LAMBDA表達(dá)式的用法
C#編程語(yǔ)言非常優(yōu)美,我個(gè)人還是非常贊同的。特別是在學(xué)習(xí)一段時(shí)間C#后發(fā)現(xiàn)確實(shí)在它的語(yǔ)法和美觀度來(lái)說(shuō)確實(shí)要比其它編程語(yǔ)言強(qiáng)一些(也可能是由于VS編譯器的加持)用起來(lái)非常舒服,而且對(duì)于C#我覺(jué)得他最優(yōu)美之處不僅僅是語(yǔ)法糖方面還有就是體現(xiàn)在LINQ和Lambda表達(dá)式。
本篇文簡(jiǎn)單介紹一下關(guān)于C#當(dāng)中LINQ表達(dá)式和其對(duì)應(yīng)的Lambda表達(dá)式的用法,關(guān)于這兩部分內(nèi)容的相關(guān)參考資料:
人民郵電出版社《C#程序設(shè)計(jì)及應(yīng)用教程》(第3版)
博客:《c# Linq查詢》
同時(shí)在介紹的時(shí)候我會(huì)盡量挑出重要部分同時(shí)加上我自己的理解和認(rèn)識(shí),如有偏差還請(qǐng)指教。
首先先讓我們看一下什么是LINQ查詢表達(dá)式和Lambda表達(dá)式:
運(yùn)行結(jié)果:
以上是對(duì)LINQ查詢表達(dá)式和Lambda表達(dá)式的一個(gè)簡(jiǎn)單的應(yīng)用,都是查詢stu列表中年齡大于等于20歲的結(jié)果并且把結(jié)果按照年齡降序排列。
由此可見(jiàn)Linq表達(dá)式和Lambda表達(dá)式并沒(méi)有什么可比性,只是用Lambda可以實(shí)現(xiàn)LINQ的查詢語(yǔ)句。
那與Lambda表達(dá)式相關(guān)的整條語(yǔ)句稱作什么呢?在微軟并沒(méi)有給出官方的命名,在《深入理解C#》中稱其為“點(diǎn)標(biāo)記”。
例子中主要以LINQ表達(dá)式為主,LINQ表達(dá)式結(jié)構(gòu)更為清晰易于理解,同時(shí)也會(huì)給出對(duì)應(yīng)的點(diǎn)標(biāo)記寫(xiě)法(所有的LINQ查詢表達(dá)式都可以轉(zhuǎn)成對(duì)應(yīng)的點(diǎn)標(biāo)記。反之,不是所有的點(diǎn)標(biāo)記都可以轉(zhuǎn)成查詢表達(dá)式。),所以如果想要了解這部分的讀者也請(qǐng)往下看。本文會(huì)介紹LINQ查詢表達(dá)式用法以及對(duì)應(yīng)的Lambda表達(dá)式。
LINQ查詢表達(dá)式是一組查詢技術(shù)的統(tǒng)稱,其主要思想是將各種查詢功能直接集成到C#語(yǔ)言中,不論是對(duì)象、XML、還是數(shù)據(jù)庫(kù)都可以用LINQ編寫(xiě)查詢語(yǔ)句。LINQ與傳統(tǒng)迭代技術(shù)實(shí)現(xiàn)的查詢優(yōu)勢(shì)在于更簡(jiǎn)明、更易讀這種優(yōu)勢(shì)特別是在篩選多個(gè)條件時(shí)更為顯著;使用很少的程序代碼便能實(shí)現(xiàn)復(fù)雜的查詢和篩選;無(wú)需修改或者是進(jìn)行很少的修改就能移植到其它的數(shù)據(jù)源。LINQ查詢語(yǔ)句并不復(fù)雜并且與SQL語(yǔ)句有些類似,學(xué)習(xí)起來(lái)難度并不大。
接下來(lái)直接看LINQ查詢例子:
//以下為例子中涉及查詢的數(shù)據(jù) List<Student> stu = new List<Student>() { new Student(){Id = 1,Name = "王同學(xué)",Age = 24}, new Student(){Id = 2,Name = "王同學(xué)",Age = 30}, new Student(){Id = 3,Name = "王同學(xué)",Age = 21}, new Student(){Id = 4,Name = "趙同學(xué)",Age = 20}, new Student(){Id = 5,Name = "錢(qián)同學(xué)",Age = 22}, new Student(){Id = 6,Name = "孫同學(xué)",Age = 23}, new Student(){Id = 7,Name = "周同學(xué)",Age = 23}, new Student(){Id = 8,Name = "吳同學(xué)",Age = 20}, new Student(){Id = 9,Name = "鄭同學(xué)",Age = 25}, new Student(){Id = 10,Name = "蔣同學(xué)",Age = 26} };
查詢年齡是30歲的王同學(xué)的信息:
//查詢年齡是30歲的王同學(xué)的信息 var res = from t in stu where t.Name == "王同學(xué)" && t.Age == 30 select t; //對(duì)應(yīng)的Lambda表達(dá)式 //var res1 = stu.Where(t => t.Age == 30 && t.Name == "王同學(xué)"); foreach (var item in res)//顯示查詢結(jié)果 { Console.Write("學(xué)號(hào):"+item.Id+"\n姓名:"+item.Name+"\n年齡:"+item.Age); }
運(yùn)行結(jié)果:
LINQ查詢表達(dá)式必須以form子句開(kāi)頭,并且必須以select或group子句結(jié)尾。在第一個(gè)from子句和最后一個(gè)select或group子句之間,查詢表達(dá)式可以包含一個(gè)或者多個(gè)where、orderby、join、let甚至附加from子句。LINQ表達(dá)式整體的用法和SQL語(yǔ)句很像,在上面的例子中就可以看出。
上面的例子的含義就是從數(shù)據(jù)源stu中查詢一個(gè)數(shù)據(jù)“t”,“t”滿足的條件就是它的Name是王同學(xué)同時(shí)它的Age是30,然后查詢這個(gè)“t”。LINQ查詢語(yǔ)句的返回值類型為IEnumerable<T>,LINQ執(zhí)行查詢時(shí),一般利用foreach循環(huán)執(zhí)行查詢得到一個(gè)序列,這這種方式稱為“延遲執(zhí)行”。
什么是“延遲執(zhí)行”?還是上面例子中的查詢:
//查詢年齡是30歲的王同學(xué)的信息 var res = from t in stu where t.Name == "王同學(xué)" && t.Age == 30 select t; //var res1 = stu.Where(t => t.Age == 30 && t.Name == "王同學(xué)");Lambda表達(dá)式寫(xiě)法 foreach (var item in res) { Console.Write("學(xué)號(hào):"+item.Id+"\n姓名:"+item.Name+"\n年齡:"+item.Age); } Console.WriteLine("\n--------------------------------------------------------------------------"); stu.Add(new Student(){Id = 11,Name = "王同學(xué)",Age = 30}); foreach (var item in res) { Console.Write("學(xué)號(hào):" + item.Id + "\n姓名:" + item.Name + "\n年齡:" + item.Age); Console.WriteLine(); }
運(yùn)行結(jié)果:
延遲查詢就是只需構(gòu)造一次查詢語(yǔ)句,可以多次使用。在List中添加新元素之后并沒(méi)有重新執(zhí)行查詢操作,然而res中的結(jié)果卻根據(jù)List中元素的改變相應(yīng)發(fā)生了改變。
從學(xué)生中選出年齡小于25歲并且按照年齡降序排列
//從學(xué)生中選出年齡小于25歲并且按照年齡降序排列 var res = from t in stu where t.Age < 25 orderby t.Age descending select t; //var res1 = stu.Where(t => t.Age < 25).OrderByDescending(t => t.Age).Select(t => t);Lambda寫(xiě)法 foreach (var item in res) { Console.Write("學(xué)號(hào):" + item.Id + "\n姓名:" + item.Name + "\n年齡:" + item.Age); Console.WriteLine(); }
運(yùn)行結(jié)果:
從學(xué)生中查詢姓王的同學(xué)的信息并且按照年齡降序排列
//從學(xué)生中查詢姓王的同學(xué)的信息并且按照年齡降序排列 var res = from t in stu from n in t.Name where n == '王'//名字中帶有王字 orderby t.Age descending select t; //var res1 = stu.Where(t => t.Name.IndexOf("王") == 0).OrderByDescending(t => t.Age);lambda表達(dá)式 foreach (var item in res) { Console.Write("學(xué)號(hào):" + item.Id + "\n姓名:" + item.Name + "\n年齡:" + item.Age); Console.WriteLine(); }
運(yùn)行結(jié)果:
學(xué)生信息按照年齡、Id進(jìn)行排序
//參數(shù)越靠前,優(yōu)先級(jí)越高 //先按age排序,當(dāng)分?jǐn)?shù)相同時(shí)再按id排序...依次類推 var res = from t in stu orderby t.Age, t.Id select t; //var res1 = stu.OrderBy(t => t.Age).ThenBy(t => t.Id);Lambda表達(dá)式 foreach (var item in res) { Console.Write("學(xué)號(hào):" + item.Id + "\n姓名:" + item.Name + "\n年齡:" + item.Age); Console.WriteLine(); }
運(yùn)行結(jié)果:
按照年齡進(jìn)行分組,查詢相同年齡數(shù)量大于2的內(nèi)容
//按照年齡進(jìn)行分組,查詢相同年齡數(shù)量大于2的內(nèi)容 var res = from t in stu group t by t.Age into s where s.Count()>=2 select s; //var res1 = stu.GroupBy(t => t.Age).Where(s => s.Count() >= 2);lambda表達(dá)式 foreach (var item in res) { foreach (var items in item) { Console.Write("學(xué)號(hào):" + items.Id + "\n姓名:" + items.Name + "\n年齡:" + items.Age); Console.WriteLine(); } Console.WriteLine(); }
運(yùn)行結(jié)果:
查詢出集合qSt中year等于集合qSc中year的元素并形成新的集合
List<s> pSt = new List<s>(); pSt.Add(new s() { year = 1999, name = "小張" }); pSt.Add(new s() { year = 2000, name = "小王" }); pSt.Add(new s() { year = 2001, name = "小李" }); pSt.Add(new s() { year = 2010, name = "小趙" }); List<school> pSc = new List<school>(); pSc.Add(new school() { year = 1999, name = "aaa" }); pSc.Add(new school() { year = 2001, name = "bbb" }); pSc.Add(new school() { year = 2002, name = "ccc" }); pSc.Add(new school() { year = 2010, name = "ddd" }); pSc.Add(new school() { year = 2012, name = "fff" }); var res = from t1 in pSc from t2 in pSt where t1.year == t2.year select new {year = t1.year, name = t1.name + t2.name}; foreach (var item in res) { Console.Write("年:" + item.year + "姓名:" + item.name); Console.WriteLine(); }
運(yùn)行結(jié)果:
并行l(wèi)inq
并行查詢可以分解查詢的工作,使其分布在多個(gè)線程上。當(dāng)pc擁有多個(gè)cpu時(shí),可以看到并行查詢帶來(lái)的改進(jìn)效果。并行LINQ適用于大型的集合查詢,并擁有一定的優(yōu)勢(shì)。使用System.Collections.Concurrent.Partitioner.Create可以手動(dòng)創(chuàng)建分區(qū)器??梢源拄?shù)恼J(rèn)為并行l(wèi)inq對(duì)于大集合的查詢是優(yōu)勢(shì)比較明顯的。取消長(zhǎng)時(shí)間運(yùn)行的并行l(wèi)inq查詢可以設(shè)置利用System.Threading.CancellationTokenSource設(shè)置取消操作。
Console.WriteLine("開(kāi)始構(gòu)造大數(shù)組..."); //構(gòu)造大數(shù)組 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("開(kāi)始計(jì)算..."); var st = System.DateTime.Now; var sum = (from x in data where x > 20 select x).Sum();//常規(guī)linq-耗時(shí)1.8641s var st2 = System.DateTime.Now; var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//并行查詢-耗時(shí)0.6620s //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查詢----x3 => x3 > 20(Lambda表達(dá)式) var st3 = System.DateTime.Now; /*Partitioner.Create 手動(dòng)創(chuàng)建分區(qū)器以及終止LINQ查詢的方法可以詳見(jiàn)文初的博客鏈接 Create具有多個(gè)重載,可依據(jù)需求進(jìn)行分區(qū)*/ 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("常規(guī)linq耗時(shí):{0}s", dt1.TotalSeconds.ToString()); Console.WriteLine("并行l(wèi)inq耗時(shí):{0}s", dt2.TotalSeconds.ToString()); Console.ReadKey();
運(yùn)行結(jié)果:
寫(xiě)在最后,如果你對(duì)以上LINQ以及對(duì)應(yīng)的Lambda的使用方法都已經(jīng)了解那你已經(jīng)初步了解了LINQ查詢表達(dá)式和Lambda表達(dá)式,這里需要說(shuō)明的一點(diǎn)是關(guān)于Lambda的使用方法并不僅僅只限于進(jìn)行查詢,他是一個(gè)主要用于簡(jiǎn)化委托的代碼編寫(xiě)形式,他用法遠(yuǎn)比文中介紹的更加廣泛,本文是為了對(duì)比展現(xiàn)LINQ和Lambda。
以上就是C# LINQ查詢表達(dá)式及對(duì)應(yīng)LAMBDA表達(dá)式的用法的詳細(xì)內(nèi)容,更多關(guān)于C# LINQ查詢表達(dá)式及LAMBDA表達(dá)式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- C#集合查詢Linq在項(xiàng)目中使用詳解
- C# Linq延遲查詢的執(zhí)行實(shí)例代碼
- c# Linq查詢?cè)斀?/a>
- c# 動(dòng)態(tài)構(gòu)建LINQ查詢表達(dá)式
- C#使用LINQ查詢表達(dá)式的基本子句總結(jié)
- C# linq查詢之動(dòng)態(tài)OrderBy用法實(shí)例
- C#中Linq延遲查詢的例子
- C#使用linq語(yǔ)句查詢數(shù)組中以特定字符開(kāi)頭元素的方法
- C#使用linq查詢大數(shù)據(jù)集的方法
- C#中Linq查詢基本操作使用實(shí)例
- C#使用LINQ查詢操作符實(shí)例代碼(一)
相關(guān)文章
C#實(shí)現(xiàn)windows form倒計(jì)時(shí)的方法
這篇文章主要介紹了C#實(shí)現(xiàn)windows form倒計(jì)時(shí)的方法,涉及C#桌面程序設(shè)計(jì)中時(shí)間操作的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04C#實(shí)體對(duì)象序列化成Json并讓字段的首字母小寫(xiě)的兩種解決方法
這篇文章主要介紹了C#實(shí)體對(duì)象序列化成Json并讓字段的首字母小寫(xiě)的兩種方法,在這兩種方法中小編比較推薦使用第二種方法,需要的朋友可以參考下2018-06-06C#自定義繁體和簡(jiǎn)體字庫(kù)實(shí)現(xiàn)中文繁體和簡(jiǎn)體之間轉(zhuǎn)換的方法
這篇文章主要介紹了C#自定義繁體和簡(jiǎn)體字庫(kù)實(shí)現(xiàn)中文繁體和簡(jiǎn)體之間轉(zhuǎn)換的方法,通過(guò)自定義繁簡(jiǎn)轉(zhuǎn)換字庫(kù)實(shí)現(xiàn)繁體與簡(jiǎn)體轉(zhuǎn)換的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04C#實(shí)現(xiàn)繪制浮雕圖片效果實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)繪制浮雕圖片效果實(shí)例,是C#程序設(shè)計(jì)中非常實(shí)用的一個(gè)功能,需要的朋友可以參考下2014-08-08WPF使用觸發(fā)器需要注意優(yōu)先級(jí)問(wèn)題解決
本文主要介紹了WPF使用觸發(fā)器需要注意優(yōu)先級(jí)問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01C#實(shí)現(xiàn)TFTP客戶端的項(xiàng)目實(shí)踐
TFTP不僅有斷點(diǎn)續(xù)傳,多用戶級(jí)別限制等功能,本文主要介紹了C#實(shí)現(xiàn)TFTP客戶端的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04C#使用Clipboard類實(shí)現(xiàn)剪貼板功能
這篇文章介紹了C#使用Clipboard類實(shí)現(xiàn)剪貼板功能的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06