把我的爱送给你――C#3.5(这题目似乎写错了)
本文發(fā)表于 中國(guó)IT實(shí)驗(yàn)室周報(bào)。這是我初次寫(xiě)給雜志社稿件,其中必有許多不足之處,還望大家見(jiàn)諒,雖然這篇文章質(zhì)量可能不太高,但我希望能將個(gè)人的這些總結(jié)與大家分享。
?
從筆者接觸編程至今,經(jīng)歷了數(shù)種編程語(yǔ)言,從Visual Basic6.0桌面程序開(kāi)發(fā)到ASP(VBScript)的網(wǎng)站開(kāi)發(fā),從C#1.1到C#2.0,再至今日的令人加心動(dòng)的C#3.5,筆者曾多次為Windows平臺(tái)下的編程感慨——越來(lái)越方便的操作,越來(lái)越強(qiáng)大的功能,越來(lái)越簡(jiǎn)潔的代碼使得由代碼組成的編程世界中平添的許多色彩與歡樂(lè)。
以上可以算作對(duì)即將要介紹的C#3.5新特性的一個(gè)鋪墊。筆者對(duì)于C#的愛(ài),勝過(guò)其他的任何語(yǔ)言,尤其對(duì)于剛剛召開(kāi)不久的微軟2008新技術(shù)大會(huì)上發(fā)布的Visual Studio 2008筆者的愛(ài)意更甚。于是,筆者決定將自己對(duì)它的愛(ài)以文章的形式來(lái)表達(dá)。
讓我們?nèi)ビ纱碎_(kāi)始,向C#3.5示愛(ài):
一、告訴C#3.5,我們對(duì)愛(ài)上它的曖昧-var關(guān)鍵字
曖昧?眾所周知,C#從出生以來(lái)都是很以一種強(qiáng)類型的語(yǔ)言示人的,并不像JavaScript和VB6.0那樣給人以“曖昧”的感覺(jué)啊?而在此處介紹的關(guān)鍵字var,是否讓您想起了JavaScript中的定義變量的關(guān)鍵字var?事實(shí)上,這兩個(gè)看似相同的關(guān)鍵字卻有本質(zhì)上的區(qū)別。而這個(gè)var關(guān)鍵字并非在C#3.5中才出現(xiàn)的,它在C#3.0中便已經(jīng)存在,筆者之所以在此介紹它,是因?yàn)橛榻B3.5,必須而且應(yīng)該去介紹一下這個(gè)在C#3.0中便出現(xiàn)的特性——本地類型推斷(Local Type Reference),如若不然,筆者內(nèi)心便無(wú)法安穩(wěn)。
在C#2.0及其以前的版本中,如若定義一可以向其賦任何值的變量,那么我們需對(duì)其以object關(guān)鍵字進(jìn)行定義,這種變量需要對(duì)值類型的進(jìn)行裝箱操作而且在對(duì)該變量使用的時(shí)候還需要進(jìn)行相應(yīng)的拆箱操作,而這種裝箱拆箱所耗費(fèi)的資源實(shí)在是筆者所不愿意看到的。
那么,我們既不愿意編寫(xiě)無(wú)謂耗費(fèi)資源的代碼,又想去實(shí)現(xiàn)object定義變量實(shí)現(xiàn)的功能,怎么辦?C#3.5為我們提供了一種變量定義方式:
(圖1,1.jpg)
看上面的變量定義,奇怪么?其實(shí)這就是C#3.5為我們提供的一種新功能——本地類型推斷,它可以保護(hù)類型安全,而且允許您編寫(xiě)更為“自由”的代碼。也就是說(shuō),我們可以不去考慮變量的類型而直接以var關(guān)鍵字去修飾它,編譯器能夠從給變量賦值的表達(dá)式中智能推斷出變量的類型。它和COM模型中的Variant關(guān)鍵字定義出的變量完全不同,COM中的Variant關(guān)鍵字是后期綁定的一種方式,在編譯期沒(méi)有檢測(cè),僅在代碼運(yùn)行時(shí)才會(huì)出現(xiàn)它自身存在的問(wèn)題,而且一不小心就會(huì)出現(xiàn)一大堆令人討厭的Bug。而C#中這個(gè)var定義的變量在編譯其便推斷出它的類型,并且編譯后的IL代碼中只包含推斷出的類型。
即上面的兩行代碼完全等同物如下代碼:
(圖二,2.jpg)
那么,既然二者等同,我們?yōu)槭裁催€要對(duì)它的這種“曖昧”情有獨(dú)衷?事實(shí)上,var關(guān)鍵字不僅僅能夠?qū)崿F(xiàn)我們?nèi)缟纤龅墓δ?#xff0c;它會(huì)成為你在使用C#3.5進(jìn)行編程時(shí)非常熟悉的一個(gè)朋友,記住這個(gè)“匿名類型(Anonymous Type)”,也記住這個(gè)“本地類型推斷(Local Type Reference)”。
二、告訴C#3.5,我們喜歡它纖細(xì)的身材——自動(dòng)屬性(Automatic Properties)
還記得我們?cè)贑#1.1和C#2.0寫(xiě)類的屬性時(shí)定義的那個(gè)小小的私有變量么?甚至有些人還因?yàn)樗接凶兞渴欠駪?yīng)該和屬性定義在一起而展開(kāi)了爭(zhēng)論。那么,現(xiàn)行社會(huì)流行的“減肥”這個(gè)詞也可以應(yīng)用到我們的程序代碼上來(lái)。
C#3.5為我們提供了自動(dòng)屬性(Automatic Properties),看如下代碼:
(圖三,3.jpg)
很奇怪么?get和set關(guān)鍵字均沒(méi)有我們以前所熟悉的return value;和_privateField=value;這樣的字眼。事實(shí)上,這就是我們的這善解人意的代碼編譯器為我們提供的最新功能自動(dòng)屬性。編譯器會(huì)為我們定義的Name屬性自動(dòng)生成一私有變量來(lái)保存其值。于是,我們?cè)瓉?lái)需要至少三行才能完成的代碼現(xiàn)在僅需一行便輕松完成了。
不過(guò),它有自身的局限性,比如說(shuō)不能在用自動(dòng)屬性定義的屬性中加邏輯判斷,get和set必須成對(duì)出現(xiàn)等。然而,筆者相信并非我們所有的屬性均要加上邏輯判斷吧?那么,就請(qǐng)去嘗試自動(dòng)屬性為我們帶來(lái)的便利。
三、奇怪的“=>”符號(hào)——lambda表達(dá)式
習(xí)慣C#編程的您在C#2.0及其以前見(jiàn)到過(guò)這個(gè)符號(hào)”=>”么?這又是一新特性,我們可以將它讀作”lambda表達(dá)式”。
C# 2.0 通用使用匿名方法引入了"傳遞指針到特定代碼"作為參數(shù)的功能。這是一個(gè)功能強(qiáng)大的概念,但是這種方式您實(shí)際傳遞的是方法的一個(gè)指針,而不是代碼塊。那個(gè)引用指向編譯時(shí)生成的強(qiáng)類型代碼。使用泛型,您可獲得更大靈活性,但是對(duì)泛型類型難以應(yīng)用標(biāo)準(zhǔn)操作符 。C# 3.0 引入 lambda 表達(dá)式,它允許使用更簡(jiǎn)練的語(yǔ)法來(lái)定義匿名方法。
看如下代碼片斷:
(圖四,4.jpg)
且不說(shuō)其他部分意義,單來(lái)看我們.Where括號(hào)之中的部分,c=>c.Address==City.Heze這段代碼,我們可以將它理解為,給定c,返回c.Address==City.Heze的記錄集,此處就是lambda表達(dá)式的應(yīng)用之一,它廣泛應(yīng)用于我們下期即將介紹的LINQ(Language Integerated Query)中。
四、為我們的愛(ài)加上更為自由的翅膀——擴(kuò)展方法
熟知Web編程的朋友們應(yīng)該對(duì)如下這段代碼很熟悉:
(圖五,5.jpg)
其中ReplaceUnSafeChars是一個(gè)進(jìn)行字符器過(guò)濾的函數(shù),將傳入的字符串中的非法字符過(guò)濾,返回一合法的字符串,它通常用于用戶向某一數(shù)據(jù)處理頁(yè)面提交數(shù)據(jù)時(shí),為了防止SQL注入或者其他非法入侵而進(jìn)行的一項(xiàng)工作。為此我們不厭其煩地寫(xiě)類庫(kù),在某一項(xiàng)目的解決方案中添加進(jìn)來(lái)自己過(guò)濾函數(shù)。這種方式是不錯(cuò),可是,能不能有一種方式讓我們更為方便,讓我們寫(xiě)出的代碼更為優(yōu)雅?
設(shè)想,如果我們能夠?qū)ο到y(tǒng)中定義的數(shù)據(jù)類型進(jìn)行擴(kuò)展,給它增加上我們自己的方法,那豈不是我們可以像strID.ToSring()那樣來(lái)實(shí)現(xiàn)我們自己的過(guò)濾方法?
不錯(cuò),想法有了,自然C#也不會(huì)讓我們失望——擴(kuò)展方法(Extension Methods)為我們來(lái)解決這一問(wèn)題。如下圖我們定義一個(gè)類:
(圖六,6.jpg)
注意,該類為靜態(tài)類,并且其中的方法Name為靜態(tài)方法,其參數(shù)o為object類型,并且有關(guān)鍵字this進(jìn)行修飾。以上這些,就是為系統(tǒng)類型進(jìn)行擴(kuò)展時(shí)的必備條件。在定義了該類的同一命名空間下的其他類中即可對(duì)所有類型使用該Name方法來(lái)獲取它的ToString()之后的值。我們看編譯器是如何來(lái)表示的:
(圖7,7.jpg)
我們看到,編譯器強(qiáng)大的智能提示功能給我們的提示是(extension) string object.Name(),這是因?yàn)槲覀兪菍?duì)object類進(jìn)行了擴(kuò)展,故我們可以對(duì)任何類型使用擴(kuò)展方法Name。
這雖然并不是一個(gè)十分大的改動(dòng),可是對(duì)于我們?cè)诖a上的可讀性及實(shí)用性都會(huì)有很大的幫助。我們習(xí)慣了從左到右的閱讀方式,習(xí)慣了在打”.”時(shí)編譯器給出智能提示,所以我們也會(huì)毫無(wú)理由的習(xí)慣“擴(kuò)展方法”。
要注意,對(duì)于值類型的變量進(jìn)行擴(kuò)展是MS推薦的,可是對(duì)于引用類型的變量進(jìn)行擴(kuò)展卻并未被推薦,因?yàn)閷?duì)于所有的調(diào)用都要?jiǎng)?chuàng)建一個(gè)對(duì)象的拷貝,而這個(gè)對(duì)象拷貝的創(chuàng)建的花銷是我們所不敢隨意忽略的。
五、令人心動(dòng)的LINQ
您想過(guò)在代碼中不寫(xiě)SQL語(yǔ)句就實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作么?當(dāng)然,筆者并不是指那種通過(guò)拖拽數(shù)據(jù)源控件如SQLDataSource等然后加個(gè)GridView或者FormView就去實(shí)現(xiàn)對(duì)數(shù)據(jù)的顯示、更新的操作。假如有一種工具能夠讓將我們數(shù)據(jù)庫(kù)中的表映射為對(duì)象,而且映射這一工作能夠自動(dòng)完成,然后我們就可以通過(guò)對(duì)這些映射過(guò)來(lái)的對(duì)象進(jìn)行操作,從而實(shí)現(xiàn)對(duì)數(shù)據(jù)表的操作了。
正如筆者上面所說(shuō),想法有了,就可以實(shí)現(xiàn)。事實(shí)上,LINQ并不是屬于C#的,更不能說(shuō)是C#3.5的特性了。不過(guò)筆者在這里提出,主要是因?yàn)樗鼘?shí)在太令人興奮而且C#3.5中的編程如果沒(méi)有了對(duì)LINQ的使用代碼就會(huì)遜色許多。
上述兩段作為您的“開(kāi)胃菜”,僅令您心動(dòng)是遠(yuǎn)遠(yuǎn)不夠的,讓我們近距離接觸一下LINQ——語(yǔ)言集成查詢(Language Integerated Query)。
筆者以LINQ對(duì)數(shù)據(jù)庫(kù)的操作來(lái)對(duì)LINQ做一下大概的介紹。
LINQ to SQL 是O/RM(對(duì)象關(guān)系映射)在.NET Framework(Visual Studio 2008)中的的一種實(shí)現(xiàn),它允許你用.NET 的類來(lái)生成一個(gè)關(guān)系型的數(shù)據(jù)庫(kù)。然后你可以用LINQ對(duì)從該對(duì)象中對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢,更新/插入/刪除。
LINQ to SQL完全支持事務(wù),視圖和存儲(chǔ)過(guò)程。它還提供了一種方便地在你的數(shù)據(jù)模型中對(duì)集合數(shù)據(jù)驗(yàn)證和業(yè)務(wù)邏輯規(guī)則的進(jìn)行驗(yàn)證的方法。
它的基本語(yǔ)法from… in..select是顯得如此優(yōu)雅,令我不得不為其用如此簡(jiǎn)潔的代碼實(shí)現(xiàn)我們以往需要寫(xiě)數(shù)行甚至數(shù)十行才能夠?qū)崿F(xiàn)的功能感到興奮。還記得我們?cè)谏厦娼榻B“=>”lambda表達(dá)式時(shí)提供的那個(gè)小例子么?
(圖8,8.jpg)
這就是最簡(jiǎn)單的LINQ實(shí)現(xiàn)。其中customers可以是我們從數(shù)據(jù)庫(kù)中映射過(guò)來(lái)的對(duì)象,也可以是我們自己定義的某類的實(shí)例。它實(shí)現(xiàn)的功能是從customers對(duì)象實(shí)例中查找出所有的Address為Heze的實(shí)例,返回值IEnumerable<Customer>類型。LINQ可以實(shí)現(xiàn)對(duì)所有實(shí)現(xiàn)了IEnumuerable接口的對(duì)象進(jìn)行查詢
事實(shí)上,LINQ不僅可以to DataSet,也不僅可以to SQL,也不僅可以to XML,筆者認(rèn)為,LINQ是可以to Everything的。
六 結(jié)語(yǔ)
以上僅僅是給筆者很大觸動(dòng)并且打動(dòng)了筆者心的若干功能的一部分,限于篇幅筆者不能一一進(jìn)行展開(kāi),望讀者見(jiàn)諒。筆者將在后續(xù)的文章中與您分享更多的知識(shí)與經(jīng)驗(yàn)。
轉(zhuǎn)載于:https://www.cnblogs.com/hanxianlong/archive/2008/05/15/1196459.html
總結(jié)
以上是生活随笔為你收集整理的把我的爱送给你――C#3.5(这题目似乎写错了)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pandas 数据怎样实现行间计算
- 下一篇: msdn中C#中常用词汇概念(转帖)