




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