課程代碼課件09-linq表達式深入_第1頁
課程代碼課件09-linq表達式深入_第2頁
課程代碼課件09-linq表達式深入_第3頁
課程代碼課件09-linq表達式深入_第4頁
課程代碼課件09-linq表達式深入_第5頁
已閱讀5頁,還剩47頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

一一 類:[C#3.0/.NET3.x新增特性不好意思,我匿在開發(fā)中,我們有時會像下面的代碼一樣一個類:可以看出,在類的語法new{}就完事了。從外部看來,我們根本無法知道這個varannoyCla1= ID= Name= Age=Console.Wri ine("ID:{0}-Name:{1}-Age:{2}",annoyCla1.ID,annoyCla1.Name,深入類背既然我們發(fā)現(xiàn)類可以完全實現(xiàn)具名類的效果,那么我們可以大膽猜測編譯器肯定在class,于是,我們還是借助反編譯工具對其進行探索。通過Reflector反編譯,我們找到了編譯器生成的類如下圖所示:<>fAnonymousType0<<ID>jTPar,<Name>jTPar,Age>jTPar>就是一個泛型(3)可以看出,類還重寫了基類的三個方法:Equals,GetHashCode和ToString;我們它為我們所生成的ToString方法是怎么來實現(xiàn)的:類的共可以想象一下,如果我們的代碼中定義了很多類,那么是不是編譯器會為每一個說,定義了多個類的話如果符合一定條件則可以共個泛型類。下面,我們就來看看有如果定義的類與之前定義過的一模一樣:屬性類型和順序都一致,那么默認共 varannoyCla1= ID= Name= Age= ine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.Name, // //02.屬性類型和順序與annoyCla1一致,那么共同使用一 varannoyCla2= ID= Name= Age= ine("ID:{0}-Name:{1}-Age:{2}", annoyCla1.Name, ine("IsTheSameClassof1and annoyCla1.GetType()== varannoyCla3= ID= Name= Age= ine("ID:{0}-Name:{1}-Age:{2}", annoyCla3.Name, ine("IsTheSameClassof2and annoyCla3.GetType()==不同的類。所以,那么可以猜測到最后兩行代碼所顯示的結果應該是False,他們雖然都使用 varannoyCla4= Name= ID= Age= ine("ID:{0}-Name:{1}-Age:{2}", annoyCla4.Name, ine("IsTheSameClassof2and annoyCla4.GetType()==通過二二 方法:[C#2.0/.NET2.0新增特性從委托的說C#中的方法是在C#2.0引入的,它終結了C#2.0之前版本委托的唯一方法是使用命名方法的時代。不過,這里我們還是看一下在沒有方法之前,我們是如何委托publicdelegatevoidDelegateTest(string編寫一個符合委托規(guī)定名方法 publicvoidTestFunc(string o,{0}", DelegateTestdgTest=newdgTest("Edison由上面的步湊可以看出,我們要一個委托實例要為其編寫一個符合規(guī)定名方法。引入了方法,使用方法委托,就會使代碼結構變得簡潔,也會省去實例化的一些引入方首先,我們來看看上面的例子如何使用方法來實現(xiàn)DelegateTestdgTest2=newDelegateTest(delegate(string{ ine("Good,{0}",

從運行結果圖中可以看出,原本需要傳遞方法名的地方我們直接傳遞一個方法,這個方法以delegate(參數(shù)){方法體}的格式編寫,在{}里直接寫了方法體內容。于是,我們不禁歡呼雀躍,又可以簡化一些工量咯其次,生成的程序通過Reflector反編譯看看方法是怎么幫我們實現(xiàn)命名法。我們可以大膽猜測:原來方法不是沒有名字的方法,還是生成了一個有名字的方法,MainC#代碼我們沒有發(fā)現(xiàn)一點可以幫助我們理解的。這時,我們想要刨根究底就有點麻煩了。還好,在高人指點下,我們知道可以借助IL(中間代碼)ReflectorCIL,就會看到另外一番天在運行時調用委托對象的Invoke方法執(zhí)行該委托對象所持有的方法。因此,我們也可以看方法擴 DelegateTestdgTest3=delegate(string ine("Goodbye,{0}", dgTest3("EdisonnewDelegateTest()也去掉了??梢?,編譯器讓我們越來越staticvoidInvokeMethod(DelegateTest dg("Edison②我們可以將已經(jīng)定義的方法地址作為參數(shù)傳入InvokeMethod方法,例如:InvokeMethod(TestFunc);當然,我們也可以使用方法,不需要單獨定義就可以調用InvokeMethod方法。InvokeMethod(delegate(string ,{0}",經(jīng)過編譯器的不斷優(yōu)化,我們發(fā)現(xiàn)連delegate后邊的()都可以省略了,我們下面InvokeMethod(delegate ine("IloveC publicdelegatevoidDelegateTest(string staticvoidInvokeMethod(DelegateTest dg("Edison stringdeletegate后面的括號之后就沒有參數(shù)了,那么結果又是什么呢?經(jīng)過調試,發(fā)現(xiàn)結果輸出的是:IloveCsharp!的參數(shù)條件呢?于是,我們帶著問題還是借助Reflector去一探究竟。①在Main函數(shù)中,可以看到編譯器為我們自動加上了符合DelegateTest這個委托定義stringIloveCsharp,但它確實是符合方法定義的,因為它會接受一個string類型的參數(shù),盡管在方法體中沒有使用到這個參數(shù)。②剛剛在Main函數(shù)中看到了方法,現(xiàn)在編譯器為我們所生成名方法三、三、擴展方法C#3.0/.NET3.x新增特性]神奇—初玩擴展方MSDN說:擴展方法使您能夠向現(xiàn)有類型“添加”方法,而無需創(chuàng)新的派生類型、重新編譯或以其他方式修改原始類型。這里的“添加之所以使用引號,是因為并沒有真正地向指定類型添加方法是乃,原來對集合進行篩選的Where()方法居然是擴展方法而不是原生的。 staticvoid List=new (){ID=1,Name="Big (){ID=2,Name="Little (){ID=3,Name="Middle //下面就使用了IEnumerable的擴展方法 vardatas p) returnp.Age>= foreach(vardatain ine("{0}-{1}- data.ID,data.Name, 上述代碼使用了Where擴展方法,找出集合中Age>=10IEblere轉到定義tem.Liq命名空間下,有叫做Enmerabeths靜態(tài)類、以及his關鍵字。publicstaticclass publicstaticIEnumerable<TSource>Union<TSource>(thisIEnumerable<TSource>first,IEnumerable<TSource>second, parer<TSource>staticpublicstatic publicstaticstring p) return p.ID,p.Name, staticvoid List=new (){ID=1,Name="Big (){ID=2,Name="Little (){ID=3,Name="Middle var vardatas returnp.Age>= foreach(vardatain 嗦嘎—探秘擴展方通過反編譯剛剛那個UseMyExtensionMethodCIL .FormatOutput()等同于調 再查看所編譯生成的方法,發(fā)現(xiàn)this關鍵已經(jīng)了。我們不禁一聲感嘆,原來this標記它是擴展的是哪一個類型,在方法體中可以對這個類型的實例進注意—總結擴展方定義靜態(tài)類,并添加public第一個參數(shù)必須附加this關鍵字;包含擴展方法所在名空間!答案:編譯器默認認為一個表達式是要使用一個實例方法,但如果沒找到,就會檢查導 名空間和當前命名空間里所有的擴展方法,匹配到適合的方法 MSDNMSDN給出的定義封裝一個方法,該方法不具有參數(shù)并且不返回C#中,該方法必須返回void)通常,這種方法用于執(zhí)行某個操作。現(xiàn)在,我們來看看如何使用ActionViewView可以清楚地看出,我們之前要先顯式了一個名為ShowValue的委托,并將對Name.DisyToWindow實例方法的分配給其委托實例。ViewViewAction下這個典型的場景,再通過Reflector反編譯工具查看編譯器到底幫我們做了什么好玩的事ListForEach 對System.Collections.Generic.List<T>的每個元素執(zhí)行指定操作 參數(shù) // System.Collections.Generic.List<T>的每個元素執(zhí)行的System.Action<T>委托。 異常 // actionnull publicvoidForEach(Action<T>可以看出,F(xiàn)orEachAction無返回值的委ViewView可以看出,我們?yōu)镕orEach方法傳遞了一個Action委托的實例,本質上是一個無返回值 Reflector反編譯工具去看看編譯器到底做了啥事,Action(這里我們可以先看看沒有Action的做法,是不是需要首先顯式了一個無返回值的委托,然后可以看出,在編譯后的代碼里邊連newAction< 在代碼中可以更加簡化。但是,首先,我們得了解到底編譯器是怎么識別Action委托的。于是,按照前兩篇的思路,在反編譯后的C#代碼看不出什么端倪的時候,切換到IL代碼一探究ILListForEachActionForEach歷依次調用委托所持有的方法,這個方法是一個符合Action委托定義的無返回值方法。至newAction<T>(),則是編譯器為我們提供的一個便利。例如,我們在使用List<>對象的ForEach方法時,我們可以這樣寫:{ ine(p.ID+"-"+p.Name+"-"+首先,由于我們是使用的List這個對象(List<>類型),所以編譯器自動識別了泛型委托的T(即指定類型)為。其次,編譯器自動將無返回值的方法轉換為了newAction<>對象。當然,如果是有返回值的方法則會轉換為指定類型的newFunc<TForEach你究竟有幾個Action可用二、有返回類型的內置二、有返回類型的內置委托—MSDNMSDN給出的定義封裝一個具有一個參數(shù)并返回TResult參數(shù)指publicdelegateTResultFunc<inT,outTResult>(TinToutTResultFuncViewViewFuncViewView當然,我們還可以借助方法更加便捷地使用ViewViewFunc委托時,不必顯式定義一個新委托并將命名方法分配給我們已經(jīng)知道Func委托是帶指定返回值類型的委托,那么我們來看看在實際開發(fā)場景的 List為例,在很多時候我們需要對從數(shù)據(jù)庫中的數(shù)據(jù)集合進行二次篩選,這時我們可以使用List集合的Select方法,一個Func委托實例作為方法參數(shù)傳遞給Select方法,就可以返回一個符合我們指定條件的新數(shù)據(jù)集合。 參數(shù) // // 類型參數(shù) // source // selector返回的值的類型 返回結果 System.Collections.Generic.IEnumerable<T>source 異常 // sourceselectornull publicstaticIEnumerable<TResult>Select<TSource,TResult>(thisIEnumerable<TSource>source,Func<TSource,TResult>selector);publicpublicclass publicstringName{get;set; List= >List, new , p) returnnew (){Name=p.Name >List p) returnnew (){Name=p.Name ③絕懶人版:借助類和泛型可以大大簡化我們的代 var var ist returnnew{Name=p.Name,AddDate=DateTime.Now 通過相信經(jīng)過上節(jié)Acton(三、返回bool類型的內置委托—三、返回bool類型的內置委托—FuncPredicateComparison于有返回值類型的委托,他們不過是兩個具體的特殊實例而已(一個返回bool類型,一個返回int類型)。MSDNMSDN給出的定義表示定義一組條件并確定指定對象是否符合這些條件的方法。publicdelegateboolPredicate<inT>(TArray和List<T>PredicatePredicate托來進行元素的搜索。于是,目光轉到List集合的FindAll方法,相信大部分童鞋都用FindAll :: 參數(shù) // System.Predicate<T>委托,用于定義要搜索的元素應滿足的條件 返回結果 System.Collections.Generic.List<T>,其中包含與指定 System.Collections.Generic.List<T> 異常 // matchnull publicList<T>FindAll(Predicate<T>FindAll現(xiàn)在我們來用一下Predicate委托:還是以那個 List集合為例,假如我們要篩選出Age>20的 ,我們就可以使用FindAll方法?,F(xiàn)在我們來寫一下這個委托:(后面我們會用Lambda表達式來簡寫,那才叫一個爽?。┛梢钥闯觯P鍵點在于: p){returnp.Age>20;}這一句上,傳入?yún)?shù)是 回的是一個比較結果即bool值。ViewView四、返回int類型的內置委托—MSDN給出的定義:表示比較同一類型的兩個對象的方法publicdelegateintComparison<inT>(Tx,TTx與y的相對值,如下表所值小于x小于y0x等于y大于x大于yArray類的Sort<T>(T[],Comparison<TList<T>的Sort(Comparison<T>)方法重載使用,用于對數(shù)組或列表中的元素進行排序。由于Comparison委托常用于在集合中進行排序,那么我們就來看看如何使用Comparison委托來進行元素的排序。于是,目光轉到List集合的Sort方法,相信大 parison<T>對整個System.Collections.Generic.List<T>中的元素進行排序。 參數(shù) // 比較元素時要使用 parison<T> 異常 // comparisonnull // 在排序過程中,comparison時,comparison可能不返回0。 publicvoidSort(Comparison<T>SortComparisonComparer次調用重載的Array.Sort靜態(tài)方法進行排序?,F(xiàn)在我們來用一下Comparison委托:還是以那個 List集合為例,假如我們要以Age為條件進行降序排列,我們應該怎么來寫這個委托呢?ViewView那么,如果是要進行升序排列呢?只需要改一下:returnp2.Age-p1.Age;更改一下被減ViewView五、LambdaC3.0/.NET3.x新增特性]回顧,發(fā)現(xiàn)上面的代碼,需要傳一個方法,寫起來特別別扭。于是我們很想知道能否有簡化的語法呢?微軟告訴咱們:OfCourseLambda表達式。Lambda表達式是比方法更簡潔的一種方法語法。Lambda來源:1920年到1930年期間,數(shù)學家AlonzoChurch人發(fā)明了Lambda積分。Lambda積分是用于表示函數(shù)的一套系統(tǒng)它使用希臘字母Lambda(λ)來表示無名函數(shù)。近年來,函數(shù)式編語言(如Lisp)使用這個術語來表示可以直接描述函數(shù)定義的表達式表達式不再需要有名字了LambdaLambda②表達式中的參數(shù)列表不一定需要包含類型refout(此時必LambdaViewViewLambda以上述案例中的Sort方法為例: List.Sort((p1,p2)=>p1.Age-So①編譯器自動生成了一個Comparison③實例化ComparisonList<TSort方法,并傳入ComparisonC#代碼獲知,而后面兩步③和④則需要通過IL代碼來分析,前面已經(jīng)介紹過相關,這里就不再贅述。回顧Lambda進化LambdaLambdaLambdaLambdaLambdaANSWER:ANSWER:語句Lambda和表達Lambda的區(qū)別在于,前者=>右邊有一個語句塊(大括號),而后者只有一個表達式(沒return和(1)表達式list.FindAll(d=>d.Id>2);//goeslist.ForEach(d=>Response.Write(d.ToString()+(2)語句list.ForEach(d=>{if(d.Id>2){+"<br/>");} 可以看出,語句Lambda的右側有一個語句塊,在這個大括號的語句可能會有多條 在System.Linq.Enumerable類中的50多個為IEnumerable<T>準備的擴展方法。Enumerable類中提供了很多的擴展方法,這里我們選擇其中幾個最ViewView篩選高手Where方Wherebool篩選器”(方法、委托、Lambda表達式均可),從而表明集合中某個元素是否應該被返回。這里,我們以上面的數(shù)據(jù)為例,篩選出集合中所有為男,大于20歲的子集合,借助Where方法實現(xiàn)如下: staticvoid List= >maleList List.Where(p p.Gender==true&&p.Age> maleList.ForEach(m=> ,而我們的amda式在編時會被轉為方法(確說應該預義泛型托實例)t投影大牛Select方Select方法可以查詢投射,返回新對象集合。這里,假設我們先篩選出所有集合,再Select方法來實現(xiàn)。 staticvoid List= > istList.Where(p p.Gender== p=>new (){Name=p.Name ist.ForEach(p=> 這里也可以采用類,可以省去事先 類的步湊,但需要配合varannoyList List.Where(pp.Gender==p=>new{Name=p.Name這里因為實現(xiàn)Lite 類重寫了ToString()方法,所以這里直接調用了排序小生OrderBy方SQLorderby了OrderBy這個方法,值得一提的就是我們可以進行多條件的排序,因為OrderBy方法返回IEnumerable<T>的類型,仍然可以繼續(xù)使用擴展方法。但要注意的是,第二次應該使用ThenBy方法。 staticvoid List= ine("OrderbyAge >orderedListList.OrderBy(p orderedList.ForEach(p=> ine("OrderbyAge orderedList List.OrderByDescending(p=> orderedList.ForEach(p=> ine("OrderbyAgeascendingandID orderedList List.OrderBy(p=> .ThenByDescending(p=> orderedList.ForEach(p=> 連接道士Join方在數(shù)據(jù)庫中,我們對兩個表或多個表進行連接查詢時往往會用到join語句,然后指定兩個表之間的關聯(lián)關系(例如:a.bid=b.aid)。在標準查詢運算符中,細心的.NET基類庫也為我們提供了Join方法?,F(xiàn)在,假設我們有兩個類: 和Children,其中每個Children對象都有一個ParentID,對應 對象的ID,現(xiàn)需要打印出所有 和Children的信息,可以借助Join方法來實現(xiàn)。 staticvoid List= List<Children>childrenList= varjoinedList p=>p.ID,c=>c.ParentID,(p,c)=> ParentID= ChildID= ParentName= ChildName= joinedList.ForEach(c=> 分組老師GroupBy方在數(shù)據(jù)庫中,我們要對查詢結果進行分組會用到groupby語句,在標準查詢運算符中,我們也有對應的GroupBy方法。這里,假設我們對 staticvoid List= >>groupsList.GroupBy(pList.GroupBy(p=> >>groupList= foreach foreach>groupin ine("Group:{0}",group.Key男女 foreachpin IEnumerable<IGrou<TKey,TSource>>類型,其中TKey是分組依據(jù)的類型,這里是根據(jù)Gender來分組的,而Gender又是bool類型,所以TKey這里為bool類型。TSource則是分組之后各個元素的類型,這里是將List< 類型,所以TSource這里為 類型,Doyouunderstandnow?GroupBy呢?不怕,我們可以使用var關鍵字嘛: varannoyGroups List.GroupBy(p=> foreach(vargroupin ine("Group:{0}", foreach(varpin 分頁實戰(zhàn)SkipTake相信很多人都使用過標準查詢運算符進行分頁操作,這里我們再次來看看如何借助Skip與Take方法來實現(xiàn)分頁操作。還是以 List集合為例,假如頁面上的表格每頁顯示5條數(shù) staticvoid 5 ine("First varfirstPageData=GetPagedListByIndex(1, firstPageData.ForEach(d=> ine("Second varsecondPageData=GetPagedListByIndex(2, secondPageData.ForEach(d=> ine("Third varthirdPageData=GetPagedListByIndex(3, thirdPageData.ForEach(d=> static >GetPagedListByIndex(intpageIndex,int >dataList= returndataList.Skip((pageIndex-1)* 淺談延遲加載與即時加在標準查詢運算符中,Where往往會使用一些ORM框架例如EF去操作數(shù)據(jù)庫,Where方法的使用則是每次調用都只是在后續(xù)生成SQL語句時增加一個查詢條件,EF無法確定本次查詢是否已經(jīng)添加結束,所以沒有辦法木有辦法在每個Where方法執(zhí)行的時候確定最終的SQL語句,只能返回一個DbQueryDbQuerySQL varsearchResult List.Where(p p.Gender==false).Where(p=>p.Age> .Where(p=>p.Name.Contains("奶茶即時加載(EagerLoading):在加載數(shù)據(jù)時就把該對象相關聯(lián)的其它表的數(shù)據(jù)一在標準查詢運算符中,F(xiàn)indAll方法就是一個典型的即時加載案例。與延遲加載相對應,F(xiàn)indAllEFSQL varsearchResult List.FindAll(p=>p.Gender== &&p.Name.Contains("奶茶二、查詢方式誰更快?LINQ:[二、查詢方式誰更快

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論