版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
1、 HYPERLINK blo/yuyijq/archive/2008/07/15/1243714.html 走進Linq-Linq橫空出世篇 某日編程大師云游到某處,見一剛畢業(yè)不久學過兩天C#和兩天SQL的coder在那里發(fā)牢騷,為啥我要寫這么多for,這么多if才能查詢出我需要的數(shù)據(jù),為啥我不能像SQL那樣,發(fā)送一條命令告訴數(shù)據(jù)庫我需要啥樣的數(shù)據(jù),它就給我返回來。 編程大師如是說:傻小子,像SQL那叫第四代編程語言,常存在于象牙塔和研究所里面的學究語言,還有個高雅的名字:函數(shù)編程。它只需要你告訴它要什么,而不需要告訴它怎么做。而你使用的C#語言屬于命令式編程,你必須像發(fā)送命令一樣一步步的告訴
2、你的機器怎么做。發(fā)牢騷的coder回了一句:不懂,我只是想不通,數(shù)據(jù)庫能做這樣的處理,為啥C#這么牛的語言不能呢。編程大師心里想著:這是不可能的事情,因為C#它是強類型語言,)*&)(&)*)()*&%&%&(后面省去200字)。天色還未晚,編程大師就急匆匆的回家了,他心里一直記著那位發(fā)牢騷的coder的話:為什么不能,為什么不能。晚上,編程大師做了一個夢,一個奇怪的夢,他的師傅“白眉”只說了三個字母:DSL。編程大師想著,DSL,領域?qū)S谜Z言,師傅要對我說什么呢,難道和今天我遇見的事有關?上面這段文字是一段調(diào)侃,調(diào)節(jié)一下氣氛,呵呵。我覺得Linq就是一種DSL,在C#等常規(guī)語言上抽象起來的,
3、面向數(shù)據(jù)處理領域的特定“語言”,當然,它的根基還是這些常規(guī)語言。select,from,where,group等關鍵字本來只是在SQL里出現(xiàn),現(xiàn)在把它們引入到C#這些常規(guī)編程語言中。那C#等是如何做到的呢?是在CLR底層支持的么?不是。既然“編譯器”可以將C#編譯成MSIL,那為什么編譯不能干更多一點事情?將這些為了領域編程而出現(xiàn)關鍵字編譯成原始語法。 下面還是從實例來說明吧:我們有一個圖書類Book,先已經(jīng)有一個填充有數(shù)據(jù)的Book集合,我們需要從這個集合里查找出單價小于50的書籍:usingSystem;/*/圖書類/publicclassBook/*/圖書名稱/publicstringT
4、itleget;set;/*/單價/publicfloatPriceget;set;/*/作者/publicstringAuthorget;set;/*/ISBN號/publicstringISBNget;set;如是我可以寫這樣的代碼:publicstaticclassHelperpublicstaticIListSearchBookByPrice()IListbooks=/./初始化一個Book集合IListresults=newList();foreach(Bookbookinbooks)if(book.Price50)results.Add(book);returnresults;現(xiàn)在
5、是根據(jù)單價查找,那如果我要按照書籍名稱查找或者按照作者查找怎么辦?那只有重寫這個方法了。但是你想想,我們的查找條件到最后只不過是一個true或者false,只要if()里面的表達式為true我們就將其添加到返回結(jié)果的集合中,我才不管里面的表達式詳細的是什么呢,ok,那這樣我們就可以進一步改進這個方法了:publicstaticclassHelperpublicdelegateboolCondtion(Bookbook);publicstaticIListSearchBook(Condtioncondition)IListbooks=/./初始化一個Book集合IListresults=newL
6、ist();foreach(Bookbookinbooks)if(condition(book)results.Add(book);returnresults;看看我們?nèi)绾握{(diào)用改進后的方法:publicboolConditionTitle(Bookbook)returnbook.Title=yuyi;IListresults=Helper.SearchBook(newCondition(ConditionTitle);我們將查詢條件使用委托解決了,只要傳遞一個接收Book作為參數(shù),返回bool值的方法進去就可以查詢滿足條件的書籍了,但是,為了這個委托,我們還得先定義一個新方法,然后。太麻煩了,
7、為此C# 2.0為我們提供了匿名方法,專門針對這些只有“一句話方法”:IListresults=Helper.SearchBook(delegate(Bookbook)returnbook.Title=yuyi;);代碼是減少不少,可這種寫法還是不“人性化”,這還是一種人向計算機妥協(xié)的結(jié)果,才產(chǎn)生了這種怪異的寫法,如是C# 3.0給我們提供了Lambda表達式:IListresults=Helper.SearchBook(book=book.Title=yuyi);代碼更短了,寫法也越來越向人類語言靠近了(這也許就是計算機語言的發(fā)展歷史,隨著計算機越來越智能,總有一天必會是計算機向人類妥協(xié))。
8、不過這里還有一點不爽,每一次調(diào)用這個查找方法都要帶Helper,要是IList自己就這個方法該多好。這個想法很好,C# 3.0里還為我們提供了擴展方法:publicstaticclassHelperpublicdelegateboolCondtion(Bookbook);publicstaticIListWhere(thisIListbooks,Condtioncondition)IListresults=newList();foreach(Bookbookinbooks)if(condition(book)results.Add(book);returnresults;仔細比較一下這個實現(xiàn)與
9、剛才的實現(xiàn)有何不同(我們還給它起了一個更好聽的名字Where,是不是和SQL更像了),現(xiàn)在我們可以這樣調(diào)用了:IListresults=books.Where(book=book.Title=yuyi);Books是一個IList,這行代碼是多么的自然而優(yōu)雅。依葫蘆畫瓢,我們可以到處這樣書寫代碼了,不僅僅可以查找書籍,還可以查找?guī)簦磺刑幚砑喜檎业姆椒ㄎ叶枷M@樣做,終于有一天你厭煩了,查找書,查找?guī)?,等等,他們之間沒有什么差異,為什么我們要做這么多重復的工作呢,所有的IList都繼承自IEnumerable,我們?yōu)樯恫唤oIEnumerable添加一個Where方法,這樣我們不就一勞永逸
10、了么,現(xiàn)在該是泛型施展才華的地方了:publicstaticclassHelperpublicdelegateboolCondtion(Tt);publicstaticIEnumerableFindBy(thisIEnumerableitems,Condtioncondition)foreach(Ttinitems)if(condition(t)/C#2.0里出現(xiàn)的一個關鍵字,返回一個迭代器yieldreturnt;現(xiàn)在,不管是IList還是IList都可以使用這個Where方法了但是做集合操作的時候我們不僅僅需要Where,還需要OrderBy,Group等等,我想把所有的SQL能干的都移植
11、過來。當然微軟也意識到了這點,如是在.net 3.5里,微軟發(fā)布了我們夢寐以求的Linq,將查詢集成到語言里面來。它給IEnumerable添加了很多擴展方法,這樣你可以很自然的去調(diào)用。你可以使用Reflector打開System.Core.dll,打開System.Linq命名空間,在這個命名空間里有一個Enumerable類,這里面就是微軟為我們添加的擴展方法,看看,是不是SQL里所有的東西都可以在這里找到了。 好了,就此擱筆吧,這一篇作為我的走進Linq系列的開篇,在接下來我會為你把Linq大卸八塊。 HYPERLINK blo/yuyijq/archive/2008/07/16/124
12、4750.html 走進Linq-輝煌的背后羅馬不是一天建成的,千里之行始于足下,美麗的Linq也不是一蹴而就的。Linq是給一些語言特性披上了一層漂亮的外衣。那紡織Linq漂亮的外衣又需要哪些金針銀線呢?在本篇有四個小節(jié),每個小節(jié)分別闡述一個語言特性,這些特性都將為Linq而服務,沒有它們也沒有未來的Linq。在文中不僅僅寫到了這些特性的用法,還揭示了他們背后發(fā)生的事情,也加上了我對這些特性的一些理解。 HYPERLINK blo/yuyijq/archive/2008/07/16/1244657.html t _blank 擴展方法 沒有擴展方法,Linq的實現(xiàn)肯定不會再像現(xiàn)在這么優(yōu)雅,在
13、本篇中我將首先描述擴展方法的應用,然后從IL層面解釋擴展方法的實現(xiàn),最后給出一些應用擴展方法的原則 HYPERLINK blo/yuyijq/archive/2008/07/16/1244736.html t _blank 匿名方法和Lambda表達式 Lambda表達式將函數(shù)式編程風格帶進了C#這種命令編程語言中,Lambda表達式可以編譯成表達式樹,將表達式樹說成Linq的根基我想一點都不為過吧 HYPERLINK blo/yuyijq/archive/2008/07/16/1244460.html t _blank 匿名類型與隱式類型局部變量如果沒有隱式類型局部變量,使用Linq查詢的時
14、候不會再像現(xiàn)在這么輕松吧 HYPERLINK blo/yuyijq/archive/2008/07/16/1244433.html t _blank 對象集合初始化器這個可以減少很多無意義的代碼這些文章我都發(fā)布在新手區(qū),這里只是做個索引,如果感興趣的可以去拍兩下磚。這一篇就算為后面的Linq鋪路吧,精彩無需等待:。 HYPERLINK blo/yuyijq/archive/2008/07/18/1245874.html 走進Linq-Linq大觀園 文章發(fā)布后大家有些人叫做,心里竊喜,不過壓力也大增,我很想按照簡潔明快的文風寫下去,不過講技術(shù)的文章很難不落于沉悶,所以我努力了。(題外話:這幾天
15、猛看幽默小說,想把文字寫的幽默一點,開個玩笑,呵呵)經(jīng)過幾天的閉關編程大師又有了一些新的覺悟了,不管對DSL還是命令式編程和函數(shù)式編程都有了新的理解。如是他又接著了漫長的云游。第一站當然就是那個曾經(jīng)讓他結(jié)下心結(jié)的那個剛畢業(yè)的coder.大師:“嘿,這幾日可好,還在發(fā)牢騷么?”Coder:“不了,正好你來了,讓你看看我的程序”,Coder將他的電腦屏幕轉(zhuǎn)向大師,期盼的眼神表明他急切的期望得到大師的夸獎。如是大師看到了如下一些代碼:/一個通用的泛型委托,代表接受一個參數(shù)并有一個返回值的方法/輸入?yún)?shù)類型/返回值類型/輸入?yún)?shù)/返回值publicdelegateTOutputMyDelegate(T
16、Inputinput);/這個類是包含有對IEnumerable接口的一系列擴展方法/因為在.net里所有的集合類都實現(xiàn)了IEnumerable接口/所以對該接口的擴展將擴散到所有集合/publicstaticclassExtensionpublicstaticIEnumerableWhere(thisIEnumerableself,MyDelegatefilter)foreach(TInputiteminself)if(filter(item)yieldreturnitem;publicstaticIEnumerableSelect(thisIEnumerableself,MyDelegat
17、eselector)foreach(TInputiteminself)yieldreturnselector(item);/下面有更多的SQL風格的移植下面是我做的個小測試代碼:publicclassProgrampublicstaticvoidMain()IListbooks=newListnewBookTitle=InsideCOM,ISBN=123-456-789,Price=20,newBookTitle=InsideC#,ISBN=123-356-d89,Price=100,newBookTitle=Linq,ISBN=123-d56-d89,Price=120;varresult=
18、books.Where(book=book.Title=Linq).Select(book=newKey=book.Title,Value=book.Price);Coder一邊展示著代碼,一邊念叨著,這里是因為使用了“擴展方法”所以可以這樣寫,這里使用了Lambda表達式,它可以簡化匿名方法的寫法,這里編程大師一邊聽著coder的講解,一遍頻頻點頭:“傻小子,不錯啊,有點當年我的影子,按照你這樣下去羅馬也可以建成了,Linq也是可以寫出來的呀。”Coder聽到大師的話興奮異常,不過他從這句話里還是捕捉到了一個陌生的詞匯:Linq。他用詫異的眼神看著大師,問道:”啥是Linq,是誰家又創(chuàng)造了個
19、新詞匯?”大師笑著說,其實你剛才做的微軟已經(jīng)幫你做了,還給它起了一個非常洋氣的名字:Linq,中文名字呢就叫做 語言集成查詢。在.net 3.5發(fā)布的時候,微軟新發(fā)布了幾個dll,其中有一個就叫做System.Core.dll,在這個dll下對一些System命名空間做了進一步擴展。在System.Core.dll下的System命名空間下你會發(fā)現(xiàn)有這么幾個泛型的委托:/無參,有一個返回值publicdelegateTResultFunc();/有一個參數(shù)和一個返回值,和你那個MyDelegate一樣publicdelegateTResultFunc(Targ);/兩個參數(shù)一個返回值publi
20、cdelegateTResultFunc(T1arg1,T2arg2);/三個參數(shù)一個返回值publicdelegateTResultFunc(T1arg1,T2arg2,T3arg3);/四個參數(shù)一個返回值publicdelegateTResultFunc(T1arg1,T2arg2,T3arg3,T4arg4);有了這幾個泛型的委托基本上都能應付了吧。還是在這個dll下有個System.Linq命名空間,這是Linq的核心命名空間,這里面有個名為 HYPERLINK http:/ Enumerable的靜態(tài)類,它里面的方法都是對IEnumerable(這個接口可是Linq的中心人物啊)這個
21、接口的擴展方法??纯矗遣皇窃赟QL里能用的這里都能找到了?Select,Where,OrderBy, HYPERLINK http:/ OrderByDescending,Average,Distinct所以你現(xiàn)在很簡單的就可以寫出像下面這樣的代碼了:result=books.Where(book=book.Title.StartsWith(I).OrderBy(book=book.Price).Select(book=newKey=book.Title,Value=book.Price);編程大師接著說:如果就這樣算了,我覺得Linq也不過爾爾,增加一些擴展方法而已,但是現(xiàn)在微軟比我們想象
22、的走的更遠,現(xiàn)在你不僅僅能對程序中的一些集合對象做這樣的查詢了,你想想我們平時的程序可以歸結(jié)為怎樣一個等式?還沒等coder說出口大師就在鍵盤上敲下:程序=代碼+數(shù)據(jù)編程大師如是接著說:那這些數(shù)據(jù)平時都來源于哪里?Coder:程序中自己構(gòu)造的一些集合對象,像我剛才的代碼中那樣,還有數(shù)據(jù)庫,這個使我們平時用到最多的,還有XML存儲,還有WebService,這個來源于遠程的數(shù)據(jù),還有什么RSS啦等等,很多了。編程大師:嗯,是的。數(shù)據(jù)的來源非常廣泛,就說我們平常用的三個吧,內(nèi)存中的集合對象、XML存儲和數(shù)據(jù)庫。對于內(nèi)存中的集合對象我們有語言自身的支持,XML我們有XML的一些API,比如XPath
23、,對于數(shù)據(jù)庫我們有ADO.net,可實際上從抽象層面我們對這些數(shù)據(jù)的操作都是相同的,你想不想屏蔽掉存儲的細節(jié),在高層有一個統(tǒng)一的API訪問這些數(shù)據(jù)呢?至于數(shù)據(jù)存儲在哪里對于你是透明的,也許它存在于你內(nèi)存中,也許在萬網(wǎng)的機房也許在美國西雅圖,但是對于你來說這些都無需關心,你的代碼都一樣。Coder:聽起來是個很美妙的事情,這不會是在做夢吧。大師:不是在做夢,今天你已經(jīng)有了這些方法在.net 3.5里微軟還發(fā)布了另外兩個dll:System.Data.Linq.dllSystem.Xml.Linq.dll在System.Data.Linq.dll里,對數(shù)據(jù)庫的查詢做了支持,不過目前微軟提供的只支持
24、Sql Server,感謝開源社區(qū),現(xiàn)在有了DbLinq,它提供了對MySql,Oracle,Sql Server,PostgreSql,Sqlite的支持。System.Xml.Linq.dll在更高層次對Xml的訪問做了支持這樣你從微軟這里獲得了:Linq to Objects 對內(nèi)存中的集合的支持Linq to Xml 對Xml的支持Linq to SQL 對Sql Server的支持 這是一張從Linq in Action那本書里的截圖,該圖很好的在一個大的層次上揭示了Linq的視圖。C#、等一系列.net語言在一些語言特性和Linq對語言的擴展上對Linq家族提供了支持。未來我們將會
25、實現(xiàn)Linq in Everywhere,Linq將成為你的變成習慣。C#對Linq的語言層面支持使用result=books.Where(book=book.Title.StartsWith(I).OrderBy(book=book.Price).Select(book=newKey=book.Title,Value=book.Price);這種方式編寫代碼,雖然減少了不少工作量,并且編程風格也更加人性化,不過現(xiàn)在C#為我們提供了一些列非常有用的關鍵字。上面的代碼現(xiàn)在你可以這樣來編寫:result=frombookinbookswherebook.Title.StartsWith(I)ord
26、erbybook.PriceselectnewKey=book.Title,Value=book.Price;from關鍵字后面跟著的是 HYPERLINK http:/ Func委托的輸入?yún)?shù),in關鍵字后面跟著一個IEnumerable類型,where,orderby,select對應著那些擴展方法,那些擴展方法接受的委托的輸入?yún)?shù)就是from后面的book。實際上你可以把這些代碼寫成一行意思就更明顯了:result=frombookinbookswherebook.Title.StartsWith(I)orderbybook.PriceselectnewKey=book.Title,Va
27、lue=book.Price;從books集合里枚舉一個book,如果這個book的標題是以”I”開頭的就把它加入到返回集合中,并把返回集合按照book的價錢排序?qū)⑸厦娴拇a編譯后的程序集用Reflector反編譯,生成的代碼是:books.Where(delegate(Bookbook)returnbook.Title.StartsWith(I);).OrderBy(delegate(Bookbook)returnbook.Price;).Select(delegate(Bookbook)returnnewKey=book.Title,Value=book.Price;);看來這種方式寫和擴
28、展方法調(diào)用的方式?jīng)]有什么差別,那為什么不呢。廢話那么多了,還是來幾個HelloWorld式的程序吧 HelloWorld Linq(下面所有程序的Book就是本系列文章中第一篇所出現(xiàn)的Book類)有一個Book集合,但是這個集合具體存儲哪里我們并不清楚,也許在內(nèi)存,也許在數(shù)據(jù)庫,也許在XML存儲,我們要做的就是把價格大于50的給揪出來,然后按照價格排序。Linq to Objects(從內(nèi)存中的集合里查找)數(shù)據(jù)準備階段/這樣的一個集合,存儲在內(nèi)存中IListbooks=newListnewBookTitle=InsideCOM,ISBN=123-456-789,Price=20,newBook
29、Title=InsideC#,ISBN=123-356-d89,Price=100,newBookTitle=Linq,ISBN=123-d56-d89,Price=120;數(shù)據(jù)查詢階段varresult=frombookinbookswherebook.Price50orderbybook.PriceselectnewKey=book.Title,Value=book.Price;foreach(variteminresult)Console.WriteLine(Key:0-Value:1,item.Key,item.Value.ToString();Linq to SQL(集合存儲在Sql
30、 Server) 數(shù)據(jù)準備階段建立數(shù)據(jù)庫表輸入數(shù)據(jù)改寫一下Book類,這個類是一個映射類,和數(shù)據(jù)庫表做映射,更多內(nèi)容后面會詳細講解TablepublicclassBook/圖書名稱/ColumnpublicstringTitleget;set;/單價/Column(DbType=numeric(5,2)publicfloatPriceget;set;/作者/ColumnpublicstringAuthorget;set;/ISBN號/ColumnpublicstringISBNget;set;數(shù)據(jù)查詢階段DataContextdb=newDataContext(DataSource=local
31、host;InitialCatalog=db;UserID=sa;Password=sa);varresult=frombookindb.GetTable()wherebook.Price50orderbybook.PriceselectnewKey=book.Title,Value=book.Price;foreach(variteminresult)Console.WriteLine(Key:0-Value:1,item.Key,item.Value.ToString();最后程序運行的結(jié)果都是:真所謂殊途同歸啊,不管數(shù)據(jù)是如何存儲的,查詢的方式卻99%一致。 總結(jié)本篇旨在給大家一個對Li
32、nq的大局觀認識,沒有詳細的深入,就算一個總覽吧。精彩無需等待,祝大家編程愉快。 HYPERLINK blo/yuyijq/archive/2008/07/16/1244433.html 不能不說的C#特性-對象集合初始化器本系列文章連接:不能不說的C#特性-對象集合初始化器 HYPERLINK blo/yuyijq/archive/2008/07/16/1244460.html t _blank 不能不說的C#特性-匿名類型與隱式類型局部變量 HYPERLINK blo/yuyijq/archive/2008/07/16/1244657.html t _blank 不能不說的C#特性-擴展方
33、法 HYPERLINK blo/yuyijq/archive/2008/07/16/1244736.html t _blank 不能不說的C#特性-匿名方法和Lambda表達式 HYPERLINK blo/yuyijq/archive/2008/07/18/1246190.html 不能不說的C#特性-迭代器(上)及一些研究過程中的副產(chǎn)品 HYPERLINK blo/yuyijq/archive/2008/07/19/1246609.html 不能不說的C#特性-迭代器(下),yield以及流的延遲計算在寫一些實體類的時候,我們往往在寫構(gòu)造方法的時候思考很長時間,除了一個無參構(gòu)造器外還在想需要
34、寫幾個構(gòu)造器呢?哪些參數(shù)是需要初始化的?,F(xiàn)在你再也不需要為這事煩惱了。C# 3.0為你提供了對象集合初始化器:/圖書類/publicclassBook/圖書名稱/publicstringTitleget;set;/單價/publicfloatPriceget;set;/作者/publicstringAuthorget;set;/ISBN號/publicstringISBNget;set;/對象初始化器Bookbook=newBookTitle=InsideCOM,ISBN=123-456-789;現(xiàn)在你想初始化幾個就初始化幾個,不需要出現(xiàn)這種情況:publicBook():this()publ
35、icBook(stringtitle):this(title,0)publicBook(stringtitle,floatprice):this(title,price,)publicBook(stringtitle,floatprice,stringisbn)this.Title=title;this.Price=price;this.ISBN=isbn;這一串的構(gòu)造方法都是為了應付不同的初始化情況。好了,來看看對象初始化器編譯器在后面為我們做了些什么呢?使用Reflector反編譯程序集:Bookg_initLocal0=newBook();g_initLocal0.Title=Insid
36、eCOM;g_initLocal0.ISBN=123-456-789;Bookbook=g_initLocal0;C#編譯器生成了一個新的局部變量g_initLocal0,調(diào)用Book的默認無參構(gòu)造方法初始化它,然后對它的屬性進行賦值,最后將這個局部變量賦值給book??吹竭@里,我們應該想到,要使用對象初始化器,那么這個對象必須有一個無參構(gòu)造方法,如果你給這個方法寫了一個有參構(gòu)造方法而將它的默認無參構(gòu)造方法覆蓋了并且沒有提供一個新的無參構(gòu)造方法,那么使用對象初始化器編譯的時候是不會通過的(不過想不通,為啥C#編譯器生成這么一個奇怪的局部變量名字,還有為啥不直接使用book呢)。像下面的代碼不更
37、好:Bookbook=newBook();book.Title=InsideCOM;book.ISBN=123-456-789;后來我發(fā)現(xiàn)我是在debug模式下編譯的,換到release模式下變成了這樣:Bookg_initLocal0=newBook();g_initLocal0.Title=InsideCOM;g_initLocal0.ISBN=123-456-789;被優(yōu)化了。上面介紹的就是對象初始化器了,那什么是集合初始化器呢?IListbooks=newList();/這里就使用了對象初始化器,學以致用吧books.Add(newBookTitle=InsideCOM,ISBN=12
38、3-456-789,Price=20);books.Add(newBookTitle=InsideC#,ISBN=123-356-d89,Price=100);books.Add(newBookTitle=Linq,ISBN=123-d56-d89,Price=120);這樣的代碼沒少寫吧,實際上也許比這更復雜,有了C# 3.0我們睡覺都想笑:IListbooks=newListnewBookTitle=InsideCOM,ISBN=123-456-789,Price=20,newBookTitle=InsideC#,ISBN=123-356-d89,Price=100,newBookTitl
39、e=Linq,ISBN=123-d56-d89,Price=120;還是像剛才一樣,我們來欣賞一下C#編譯器為我們生成的代碼:Listg_initLocal0=newList();Bookg_initLocal1=newBook();g_initLocal1.Title=InsideCOM;g_initLocal1.ISBN=123-456-789;g_initLocal1.Price=20f;g_initLocal0.Add(g_initLocal1);Bookg_initLocal2=newBook();g_initLocal2.Title=InsideC#;g_initLocal2.IS
40、BN=123-356-d89;g_initLocal2.Price=100f;g_initLocal0.Add(g_initLocal2);Bookg_initLocal3=newBook();g_initLocal3.Title=Linq;g_initLocal3.ISBN=123-d56-d89;g_initLocal3.Price=120f;g_initLocal0.Add(g_initLocal3);從上面的代碼來看,編譯器自動的調(diào)用了List的無參構(gòu)造方法,然后實例化一個個的Book,再一個個的Add進去,和我們原來的做法沒有什么不同,但是,這是編譯器為我們做的,所以簡省了我們很多的
41、編碼工作。 對象集合初始化器就算介紹完了。有人也許會說,不就是個syntx sugar么,有什么。是的,確實是個語法糖。在編譯器發(fā)展早期,編譯器科學家門一直在想方設法的優(yōu)化編譯器生成的代碼,這個時候,編譯器做的主要是對機器優(yōu)化,因為那個時候機器的時間非常寶貴,機器運算速度也不快,今天我們有了足夠好的機器了(但并不是說我們可以不關注性能的編寫程序),而且作為編寫軟件的人來說,比機器的時間寶貴得多,所以今天的編譯器也在向人優(yōu)化了,從編程語言的發(fā)展之路來講,今天的編程語言比昨天的語言更高級,也更人性化了,我們只要編寫更少的代碼,更符合人的思維的代碼,而只要關注我們值的關注的地方。體力活兒就交給編譯器
42、吧。附加:剛開始想想這對象集合初始化器也許就一雞肋,沒啥用,不就減少一點點代碼么,像這種簡單的初始化工作,大部分代碼生成器都可以來干。后來在研究匿名類型的時候突然發(fā)現(xiàn),如果沒有這個對象初始化器,匿名類型是不是要復雜一些?或者就是難以實現(xiàn)?var test = newKey=test,Value=test;如果沒有對象初始化器,匿名類型該怎么辦? HYPERLINK blo/yuyijq/archive/2008/07/16/1244460.html 不能不說的C#特性-匿名類型與隱式類型局部變量本系列文章連接: HYPERLINK blo/yuyijq/archive/2008/07/16/1
43、244433.html t _blank 不能不說的C#特性-對象集合初始化器不能不說的C#特性-匿名類型與隱式類型局部變量 HYPERLINK blo/yuyijq/archive/2008/07/16/1244657.html t _blank 不能不說的C#特性-擴展方法 HYPERLINK blo/yuyijq/archive/2008/07/16/1244736.html t _blank 不能不說的C#特性-匿名方法和Lambda表達式 HYPERLINK blo/yuyijq/archive/2008/07/18/1246190.html 不能不說的C#特性-迭代器(上)及一些研
44、究過程中的副產(chǎn)品 HYPERLINK blo/yuyijq/archive/2008/07/19/1246609.html 不能不說的C#特性-迭代器(下),yield以及流的延遲計算 在本篇中我要介紹兩個概念,我覺得這兩個東西必須一起來介紹,這樣才能連貫。C# 2.0里我們已經(jīng)匿名方法了,現(xiàn)在類型也玩起匿名來了,怪不得大家“舉報”的時候都喜歡匿名,為啥?因為匿名被舉報人就找不著報復對象了唄,是的,匿名就是把名字隱藏起來,沒有名字誰還能找得到你啊。 匿名類型在C#里有這樣一些類型,它是作為臨時儲存數(shù)據(jù)的,生命周期只在這個方法內(nèi),方法結(jié)束了,這個類型的生命周期也沒有了。那么這里我們就可以使用一個
45、匿名類型。varKeyPair=newKey=”yuyi”,Value=”20”;這個KeyPair就是一個匿名類型,注意KeyPair這里是一個變量名,并不是類的名字。嗯,前面還有一個var,這又是什么呢?這是C# 3.0里面的隱式局部變量。隱式類型局部變量還是先介紹一下隱式類型局部變量吧:在C# 3.0里多了一個關鍵字var,他表示這樣的一種類型:C#編譯器可以根據(jù)上下文推斷的出來比如var I = 5;編譯器可以根據(jù)后面的賦值推斷的出來i應該是個整型。既然是局部變量,那么它就只能用在方法內(nèi)部了,注意C#是強類型的,引入了一個var并不是像javascript那樣,變成了一個弱類型的語言。
46、在編譯器第一次編譯后var就會被確定的類型所替代的。所以對于隱式類型局部變量要注意以下幾點: 1. 它只能存在于方法內(nèi)部2. 它不是一個新的類型,只是一個關鍵字,或者叫做一個占位符,在C#編譯器編譯后它就會被確定的類型所替代3. 它是編譯器根據(jù)上下文推斷出來的,所以所有一切不能被編譯器推斷出來的用法都是錯誤的。比如不能這樣使用:var nullValue = null;因為null啥也不是,他是一個空指針,是一個不確定的東西。也不能這樣使用:var I = 5;I = “abc”;編譯器根據(jù)第一個賦值會推斷出它是一個整型,但是隨后又將一個字符串賦值給它,這是怎么回事呢?對于var我的建議是不到
47、逼不得已的時候不用,那什么是逼不得已呢?來看我們的匿名類型吧?;氐侥涿愋蛣偛耪f了,匿名類型是沒有名字的類型,沒有名字你怎么來稱呼它,怎么來聲明它?但是匿名類型真的是沒有名字的么?看看C#編譯器又在我們背后干了些什么:使用ILDASM打開編譯過的程序集,發(fā)現(xiàn)多了一個類型:f_AnonymousType0j_TPar,j_TPar這個類型是直接繼承自System.Object的,并且是internal seald(只在程序集內(nèi)可見,并且不能被繼承)。有心的你也許會發(fā)現(xiàn),這個類型還是一個泛型類型,那么只要我們在使用一個匿名類型的時候參數(shù)個數(shù),參數(shù)名稱不發(fā)生變化,編譯器是不會為我們產(chǎn)生更多的類型的:
48、varKeyPair1=newKey=yuyi,Value=Programer;varKeyPair2=newKey=y,Value=3;varKeyPair3=newKey=4,Value=abc;上面三個匿名類型,編譯器只會為我們在背后產(chǎn)生一個新類型,一個泛型的新類型。如果我們將這個匿名類型內(nèi)的屬性名修改一下:對varKeyPair1=newKey=yuyi,Value=Programer;varKeyPair2=newKey=y,Value1=3;就會產(chǎn)生兩個新泛型了:f_AnonymousType0j_TPar,j_TParf_AnonymousType1j_TPar,j_TPar看看
49、,這個命名還是有規(guī)律可循哦。如果你給這個匿名類型添加一個新屬性呢?這樣又產(chǎn)生了一個新類型了:f_AnonymousType1j_TPar,j_TPar,j_TPar嗯,這個問題還是值得關注的,所以我們在使用匿名類型的時候應該盡量保持“一致性”:屬性個數(shù)一致(這個盡量了)。屬性名稱一致,這個比較好把握。只要保持了這個一致性,編譯器會為一致的產(chǎn)生同一個類型,而不一致的會新產(chǎn)生一個類型,如果不一致的太多我想是不是會產(chǎn)生“代碼爆炸”而致使”WorkSet”過大造成性能的損失?這個只是我個人認為,沒有經(jīng)過測試。繼續(xù)隱式類型局部變量由于匿名類型在我們編寫代碼的時候并不存在,所以匿名類型也不能作為方法的返回
50、值和參數(shù)了?!眝ar”一樣,也是只能在方法內(nèi)部使用?,F(xiàn)在是不是有點明白什么時候才是逼不得已使用”var”啊?就是在使用匿名類型的時候,匿名類型編譯器可以推斷出來,但是靠人工又無法推斷了。所以我覺得只在編譯器可推斷而人不可推斷的時候才使用隱式類型局部變量,靠我們?nèi)斯た梢酝茢嗟倪€是不建議使用,顯式的聲明變量類型可以增強代碼的可讀性,這是一個好的編程習慣,不要因為C# 3.0提供了這樣的特性就大用而特用。 HYPERLINK blo/yuyijq/archive/2008/07/16/1244657.html 不能不說的C#特性-擴展方法本系列文章連接: HYPERLINK blo/yuyijq/a
51、rchive/2008/07/16/1244433.html t _blank 不能不說的C#特性-對象集合初始化器 HYPERLINK blo/yuyijq/archive/2008/07/16/1244460.html t _blank 不能不說的C#特性-匿名類型與隱式類型局部變量不能不說的C#特性-擴展方法 HYPERLINK blo/yuyijq/archive/2008/07/16/1244736.html t _blank 不能不說的C#特性-匿名方法和Lambda表達式 HYPERLINK blo/yuyijq/archive/2008/07/19/1246609.html 不
52、能不說的C#特性-迭代器(下),yield以及流的延遲計算在我們的編程生涯中我們要使用很多很多類庫,這些類庫有的是我們自己開發(fā)的,我們有她的代碼,有的是第三方發(fā)布的,我們不僅沒有他們的代碼,連看的機會都沒有。作為.net程序員,我們每天都要和BCL(Base Class Linbrary)打交道。無疑,BCL做為一個年輕的框架類庫,她是成功的,但是還有一些時候我們還是得寫一些”Helper”方法來擴展類庫,由于我們不能修改類庫的源代碼,我們只有寫一個個的靜態(tài)類。雖然在使用上也算方便,但作為追求完美的程序員來說總有些不雅。現(xiàn)在我就碰到這樣的事情,前兩天奉命寫一個從XML文件加載Chart圖的設置
53、的方法,從XML加載數(shù)據(jù)綁定到對象上,這肯定是反射的用武之地了。我經(jīng)常需要寫一些根據(jù)對象屬性名字來判斷這個對象是否有這個屬性或者根據(jù)屬性名獲取該屬性的值。還是按照平常一樣,我很快寫了一個PropertyHelper,里面有兩個靜態(tài)方法:HasProperty,GetValueByName。PropertyHelper.HasProperty(point, X),如此的調(diào)用也還過得去,不過在C# 3.0微軟為我們提供了擴展方法。現(xiàn)在我們可以直接這樣調(diào)用了point.HasProperty(“X”);看看我是如何實現(xiàn)這個擴展方法的?publicstaticclassPropertyExtensio
54、npublicstaticobjectGetValueByName(thisobjectself,stringpropertyName)if(self=null)returnself;Typet=self.GetType();PropertyInfop=t.GetProperty(propertyName);returnp.GetValue(self,null);我給object類型添加了一個擴展方法,在.net里所有的類都繼承自object,那所有的類都默認的擁有這個方法了,真方便,呵呵。注意到和普通的靜態(tài)方法有何差別?在這個方法的第一個參數(shù)前面多了一個this關鍵字。擴展方法:1 方法所在
55、的類必須是靜態(tài)的2 方法也必須是靜態(tài)的3 方法的第一個參數(shù)必須是你要擴展的那個類型,比如你要給int擴展一個方法,那么第一個參數(shù)就必須是int。4 在第一個參數(shù)前面還需要有一個this關鍵字。按照上面的步驟寫你就得到了一個“擴展方法”,你可以像調(diào)用這個類的原生方法那樣去調(diào)用它:stringstr=abc;objectlen=str.GetValueByName(Length);好像string類型現(xiàn)在有了GetValueByName這個方法一樣,但實際上string并沒有這樣一個方法。那這又是為什么呢?是我們可愛的編譯器在其中做了手腳。為了避開編譯器的干擾,我們來直接欣賞MSIL代碼:L_00
56、08:ldstrLengthL_000d:callobjectTestLambda.PropertyExtension:GetValueByName(object,string)從MSIL中我們可以看出,這段代碼編譯后和調(diào)用靜態(tài)方法沒有任何的差別(從call指令來看,這是在調(diào)用一個靜態(tài)方法)。從這里可以知道擴展方法即可以使用實例調(diào)用的方式也可以直接使用靜態(tài)類調(diào)用的方式:str.GetValueByName(Length);PropertyExtension.GetValueByName(str,Length);下面將對擴展方法做一些細節(jié)的介紹:Visual Studio 2008對擴展方法有智
57、能感知的支持,如下圖: 在方法的圖標上有一個與其他的都不相同,他的突變下面還帶有一個藍色的向下的箭頭,這就表明這個方法是一個擴展方法。下面是對編寫擴展方法要注意的幾個原則(當然,仁者見仁、智者見智,這也是一家之言):擴展方法有就近原則,也就是如果在你的程序里有兩個一模一樣的擴展方法,一個和你的使用類是處于同一命名空間里,另外一個處于別的命名空間里,這個時候會優(yōu)先使用同一命名空間里的擴展方法,也就是說“血緣關系”越近,越被青睞。很多人看到擴展方法也許眼里冒出金光,以后在設計的時候不管三七二十一,反正可以擴展。還有一些人會對類任意擴展,將以前一些作為”Helper”的方法統(tǒng)統(tǒng)使用擴展方法代替,注意
58、的是擴展方法有“污染性”,所以我覺得在擴展的時候還是想想,是不是值得這樣擴展。在擴展的時候也不要對比較高層的類進行擴展,像我上面對object的擴展我覺得就是不可取的,object是所有類的基類,一經(jīng)擴展,所有的類都被“污染”了。發(fā)表與2008-07-16 于2008-08-06第一次更新 HYPERLINK blo/yuyijq/archive/2008/07/16/1244736.html 不能不說的C#特性-匿名方法和Lambda表達式本系列文章連接: HYPERLINK blo/yuyijq/archive/2008/07/16/1244433.html t _blank 不能不說的C
59、#特性-對象集合初始化器 HYPERLINK blo/yuyijq/archive/2008/07/16/1244460.html t _blank 不能不說的C#特性-匿名類型與隱式類型局部變量 HYPERLINK blo/yuyijq/archive/2008/07/16/1244657.html t _blank 不能不說的C#特性-擴展方法不能不說的C#特性-匿名方法和Lambda表達式 HYPERLINK blo/yuyijq/archive/2008/07/18/1246190.html 不能不說的C#特性-迭代器(上)及一些研究過程中的副產(chǎn)品 HYPERLINK blo/yuyi
60、jq/archive/2008/07/19/1246609.html 不能不說的C#特性-迭代器(下),yield以及流的延遲計算 在我們程序中,經(jīng)常有這樣一些需求:1. 需要一個臨時方法,這個方法只會使用一次,或者使用的很少。2. 這個方法的方法體很短,以至于比方法聲明都短,寫起來實在沒勁(我將其稱之為“一句話方法”)。沒辦法,這樣的方法寫起來真是吃力不討好,比如一些按鈕事件處理中,有些按鈕點擊就是彈出一個對話框,或者調(diào)用一下別的什么方法。比如下面的代碼:this.btnRefresh.Click+=newSystem.EventHandler(this.btnRefresh_Click);
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 蘇州科技大學天平學院《展示設計》2022-2023學年第一學期期末試卷
- 2024腳手架搭設合同
- 2024辦公文檔范本土地使用權(quán)出讓轉(zhuǎn)讓合同公證書
- 農(nóng)業(yè)科學與農(nóng)村公共設施考核試卷
- 家用紡織品的品牌知名度與市場認知度考核試卷
- 利樂線質(zhì)量管理培訓
- 《變形縫設置專題》課件
- 糖尿病飲食及健康宣教
- 原材料采購年終總結(jié)
- 免疫應答(免疫學檢驗技術(shù)課件)
- 冠狀動脈粥樣硬化性心臟病護理查房-257
- 北師大版三年級數(shù)學上冊原創(chuàng)天天練
- 衢州江山市交投人力資源有限公司招聘筆試題庫2024
- 職業(yè)資格證書遺失補發(fā)申請表
- 九年級化學上冊 第1單元 走進化學世界教案 (新版)新人教版
- 18慈母情深 第二課時公開課一等獎創(chuàng)新教學設計
- 2024年部編新改版語文小學三年級上冊第五單元測試題及答案
- 2024年全國數(shù)據(jù)應用大賽“數(shù)字安全賽”備賽試題庫(含答案)
- 上市公司并購重組對股價的影響分析開題報告(修改)
- (必會)企業(yè)人力資源管理師(三級)近年考試真題題庫(含答案解析)
- 2024年職業(yè)院校技能大賽數(shù)字化裝備制造技術(shù)賽項理論題庫(備賽500題)
評論
0/150
提交評論