




付費(fèi)下載
下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、微軟鋒利的刀 C#40新特性之動態(tài)編程.txt愛空空情空空,自己流浪在街中;人空空錢空空,單身苦命在打工;事空空業(yè)空空,想來想去就發(fā)瘋;碗空空盆空空,生活所迫不輕松。總之,四大皆空! 本文由dhloveyzk貢獻(xiàn) doc文檔可能在WAP端瀏覽體驗(yàn)不佳。建議您優(yōu)先選擇TXT,或下載源文件到本機(jī)查看。 近幾年來,在 TIOBE 公司每個(gè)月發(fā)布的編程語言排行榜1中,C#總是能擠 進(jìn)前 10 名,而在近 10 年的編程語言排行榜中,C#總體上呈現(xiàn)上升的趨勢。C# 能取得這樣的成績,有很多因素在起作用,其中,它在語言特性上的銳意進(jìn)取讓 人印象深刻(圖 1)。 2010 年發(fā)布的 C# 4,最大的創(chuàng)新點(diǎn)是
2、擁有了動態(tài)編程語言的特性。 1 動態(tài)編程語言的中興 動態(tài)編程語言并非什么新鮮事物,早在面向?qū)ο缶幊陶Z言成為主流之前,人 們就已經(jīng)使用動態(tài)編程語言來開發(fā)了。即使在 Java、C#、C+等面向?qū)ο缶幊陶Z 言繁榮興旺、大行于世的年代,動態(tài)編程語言也在“悄悄”地攻城掠地,占據(jù)了 相當(dāng)?shù)拈_發(fā)領(lǐng)域,比如 JavaScript 業(yè)已成為 Web 客戶端事實(shí)上的主流語言。 最近這幾年,動態(tài)編程語言變得日益流行,比如 Python、Ruby 都非?;钴S, 使用者眾多。 這里有一個(gè)問題, 為什么我們需要在開發(fā)中應(yīng)用動態(tài)編程語言?與 C#和 Java 這類已經(jīng)非常成熟且功能強(qiáng)大的靜態(tài)類型編程語言相比,動態(tài)編程語言有
3、何優(yōu) 勢? 簡單地說,使用動態(tài)編程語言開發(fā)擁有以下的特性: (1)支持 REPL(Read-evaluate-print Loop:“讀入à執(zhí)行à輸出”循環(huán)迭代) 的開發(fā)模式,整個(gè)過程簡潔明了,直指問題的核心。 舉個(gè)簡單的例子, 2 所示為使用 IronPython2編程計(jì)算 圖 “1+2+100” 的屏幕截圖,我們可以快速地輸入一段完成累加求和的代碼,然后馬上就可以看 到結(jié)果: 圖 2 使用 IronPython 編程 如果使用 C#開發(fā)就麻煩多了,您得先用 Visual Studio 創(chuàng)建一個(gè)項(xiàng)目,然 后向其中添加一個(gè)類,在類中寫一個(gè)方法完成求和的功能,再編寫調(diào)用這一方
4、法 的代碼,編譯、排錯,最后才能得到所需的結(jié)果 很明顯,對于那些短小的工作任務(wù)而言,動態(tài)編程語言所具備的這種 REPL 開發(fā)模式具有很大的吸引力。 (2)擴(kuò)展方便。用戶可以隨時(shí)對代碼進(jìn)行調(diào)整,需要什么功能直接往動態(tài)對 象上“加”就是了,不要時(shí)又可以移除它們。而且這種修改可以馬上生效,并不 需要像 C#那樣必須先修改類型的定義和聲明,編譯之后新方法才可用。 換句話說:使用動態(tài)語言編程,不需要“重量級”的 OOAD,整個(gè)開發(fā)過程 迭代迅速而從不拖泥帶水。 (3)動態(tài)編程語言的類型解析是在運(yùn)行時(shí)完成的,可以省去許多不必要的類 型轉(zhuǎn)換代碼,因此,與靜態(tài)編程語相比,動態(tài)編程語言寫的代碼往往更緊湊,量 更
5、少。 動態(tài)編程語言主要的弱點(diǎn)有兩個(gè): (1)代碼中的許多錯誤要等到運(yùn)行時(shí)才能發(fā)現(xiàn),而且需要特定的運(yùn)行環(huán)境支 持,對其進(jìn)行測試不太方便,也不支持許多用于提升代碼質(zhì)量的各種軟件工程工 具,因此不太適合于開發(fā)規(guī)模較大的、包容復(fù)雜處理邏輯的應(yīng)用系統(tǒng)。 (2)與靜態(tài)編程語言相比,動態(tài)編程語言編寫的程序性能較低。不過隨著計(jì) 算機(jī)軟硬件技術(shù)的不斷進(jìn)步,比如多核 CPU 的廣泛應(yīng)用,動態(tài)編程語言引擎和運(yùn) 行環(huán)境不斷地優(yōu)化,動態(tài)編程語言編寫的程序性能在不斷地提升,在特定的應(yīng)用 場景下,甚至可以逼近靜態(tài)語言編寫的程序。 擁抱“動態(tài)編程” 2 擁抱“動態(tài)編程”特性的 C# 4 為了讓 C#、 Visual Basi
6、c 等.NET 編程語言能具備動態(tài)編程語言的特性, .NET 4.0 引入了一個(gè)“DLR(Dynamic Language Runtime:動態(tài)語言運(yùn)行時(shí))”(圖 3)。 DLR 運(yùn)行于 CLR 之上,提供了一個(gè)動態(tài)語言的運(yùn)行環(huán)境,從而允許 Python、 Ruby 等動態(tài)語言編寫的程序在.NET 平臺上運(yùn)行,同時(shí),現(xiàn)有的.NET 靜態(tài)類型編 程語言,比如 C#和 Visual Basic,也可以利用 DLR 而擁有一些動態(tài)編程語言的 特性。 (1)使用 (1)使用 C# 4 編寫動態(tài)的代碼 C# 4 新增了一個(gè) dynamic 關(guān)鍵字,可以用它來編寫“動態(tài)”的代碼。 例如, 以下代碼創(chuàng)建了一
7、個(gè) ExpandoObject 對象(注意必須定義為 dynamic): dynamic dynamicObj = new ExpandoObject(); 這一對象的奇特之處在于,我們可以隨時(shí)給它增加新成員: dynamicObj.Value = 100; /添加字段 dynamicObj.Increment = new Action() => dynamicObj.Value+); /添 加方法 這些動態(tài)添加的成員與普通的類成員用法一樣: for (int i = 0; i < 10; i+) dynamicObj.Increment();/調(diào)用方法 Console.Write
8、Line("dynamicObj.Value=0",dynamicObj.Value);/訪問 字段 ExpandoObject 對象實(shí)現(xiàn)了 IDictionary 接口,可看成是一個(gè)字典對象,所 有動態(tài)添加的成員都是這個(gè)字典對象中的元素,這意味我們不僅可以添加新成 員,還可以隨時(shí)移除不再需要的成員: /移除 Increment 方法 (dynamicObj as IDictionary).Remove("Increment"); 方法移除之后,再嘗試訪問此方法將引發(fā) RuntimeBinderException 異常。 (2) (2)使用 dynami
9、c 關(guān)鍵字簡化與 COM 組件交互的代碼 要在.NET 這個(gè)“托管世界”里調(diào)用“非托管世界”中的 COM 組件,我們必 須通過 “互操作程序集(Interop Assembly)”作為橋梁,“互操作程序集”定 義了 CLR 類型與 COM 類型之間的對應(yīng)關(guān)系。 只要給.NET 項(xiàng)目添加對“互操作程序集”的引用,就可以在.NET 應(yīng)用程序 中創(chuàng)建這一程序集所包容的各種類型的實(shí)例(即 COM 包裝器對象), 對這些對象的 方法調(diào)用(或?qū)ζ鋵傩缘拇嫒?將會被轉(zhuǎn)發(fā)給 COM 組件。 以調(diào)用 Word 為例,在 C# 4.0 之前您可能經(jīng)常需要編寫這樣的代碼: Object wordapp = new
10、Word.Application(); /創(chuàng)建 Word 對象 Object fileName = “MyDoc.docx” ;/指定 Word 文檔 Object argu = System.Reflection.Missing.Value; Word.Document doc = wordapp.Documents.Open(ref fileName, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu, ref argu,
11、ref argu, ref argu, ref argu); 上述對 Open()方法的調(diào)用語句只能用“恐怖”一詞來形容,其原因是 Word 組件中的 Open()方法定義了太多的參數(shù)。 C#4 使用 dynamic 關(guān)鍵字,配合從 Visual Basic 中學(xué)來的“命名參數(shù)與可 選參數(shù)”這兩個(gè)新語法特性,可以寫出更簡潔的代碼: dynamic wordapp = new Word.Application(); dynamic doc = wordapp.Documents.Open(FileName: “MyDoc.docx”); 上述代碼中省去了用不著的參數(shù),并且可以去掉參數(shù)前的 ref
12、 關(guān)鍵字。 當(dāng)上述代碼運(yùn)行時(shí),DLR 會使用反射技術(shù)將 dynamic 表達(dá)式“綁定(bind)” 到 COM 互操作程序集中所包容的 Word.Application 代理對象。 (3)C# 4 動態(tài)編程技術(shù)內(nèi)幕 C#4 中所定義的 dynamic 變量可以引用以下類型的對象: l 傳統(tǒng)的“靜態(tài)”的 CLR 對象。 l COM 包裝器對象。前面已經(jīng)介紹了這方面的內(nèi)容。 l 實(shí)現(xiàn)了 IDynamicMetaObjectProvider 接口的 “動態(tài)對象” ExpandoObject , 就是這種類型對象的實(shí)例。 l 基于 DLR 實(shí)現(xiàn)的動態(tài)語言(比如 IronRuby 和 IronPytho
13、n)所創(chuàng)建的對象。 從 C#程序員角度來看,所有這四種對象都是一樣的,都可用一個(gè) dynamic 變量引用之,而 DLR 在程序運(yùn)行時(shí)動態(tài)地將方法調(diào)用和字段存取請求“綁定”到 真正的對象上。 dynamic 的功能是由 DLR 所支撐的,是 C#編譯器與 DLR 分工合作的成果。 請看以下示例代碼: dynamic d = 100; d+; C#編譯器在處理上述代碼時(shí),它并不去檢查變量 d 是否可以支持自增操作, 而是為其創(chuàng)建了一個(gè) CallSite 對象(<>p_Site1): private static class <Main>o_SiteContainer0 p
14、ublic static CallSite<Func<CallSite, object, object>> <>p_S ite1; 中文 MSDN 將 CallSite 譯為“動態(tài)(調(diào)用)站點(diǎn)”,它是 DLR 中的核心組件之 一。 動態(tài)站點(diǎn)對象通過 CallSite.Create()方法創(chuàng)建, C#編譯器會為其指定一 個(gè)派生自 CallSiteBinder 的對象(稱為“動態(tài)站點(diǎn)綁定對象”)作為其參數(shù)。 動態(tài)站點(diǎn)綁定對象是與具體語言相關(guān)的,比如 IronPython 和 C#都有各自的 動態(tài)站點(diǎn)綁定對象。 動態(tài)站點(diǎn)綁定對象的主要工作是將代碼中的動態(tài)表達(dá)式(本
15、例中為 d+)轉(zhuǎn) 換為一棵“抽象語法樹(AST:Abstract Syntax Tree)”,這棵語法樹被稱為“DLR Tree”,是在.NET 3.5 所引入的 LINQ 表達(dá)式樹的基礎(chǔ)上擴(kuò)充而來的,因此,有 時(shí)又稱其為“表達(dá)式樹(Expression Tree)” DLR 在內(nèi)部調(diào)用此表達(dá)式樹的 Compile()方法生成 IL 指令, 得到一個(gè)可以被 CLR 所執(zhí)行的委托(在本例中其類型就是 Func)。 動態(tài)調(diào)用站點(diǎn)對象(本例中為<>p_Site1)有一個(gè) Target 屬性,它負(fù)責(zé)引用 這一生成好的委托。 委托生成之后,動態(tài)表達(dá)式的執(zhí)行就體現(xiàn)為委托的執(zhí)行,其實(shí)參由 C#編
16、譯 器直接“寫死”在 IL 代碼中。 簡化的代碼示意如下(通過 Reflector 得到,為便于閱讀,修改了變量名): object d = 100; object CS$0$0000 = d; if (<>p_Site1 = null) <>p_Site1 = CallSite<Func<CallSite, object, object>>.Create (); d = <>p_Site1.Target(<>p_Site1, CS$0$0000); 上述類型推斷、方法綁定及 IL 代碼生成的工作都是在程序運(yùn)行時(shí)完成的。
17、(4)動態(tài)代碼很慢嗎? (4)動態(tài)代碼很慢嗎? 動態(tài)代碼很慢嗎 動態(tài)編程語言易學(xué)易用, 代碼緊湊, 開發(fā)靈活, 但性能則一直是它的 “軟肋” 。 為了提升性能,DLR 設(shè)計(jì)了一個(gè)三級緩存策略。 動態(tài)站點(diǎn)綁定對象會為動態(tài)調(diào)用表達(dá)式轉(zhuǎn)換而成的語法樹加上相應(yīng)的測試 條件(稱為“test”),構(gòu)成一個(gè)“規(guī)則(Rule)”,這個(gè)規(guī)則可以用于判斷某個(gè)語 法樹是否可用于特定的動態(tài)調(diào)用表達(dá)式。 舉個(gè)例子,請看以下這個(gè)動態(tài)表達(dá)式: d1 + d2 如果在程序運(yùn)行時(shí) d1 和 d2 都是 int 類型的整數(shù),則 DLR 生成的規(guī)則為: if( d1 is int && d2 is int) /測試
18、條件 return (int)d1+(int)d2; /語法樹 DLR 通過檢查規(guī)則中的“測試條件”,就可以知道某個(gè)動態(tài)表達(dá)式是否可以 使用此規(guī)則所包容的語法樹。 “規(guī)則”是 DLR 緩存的主要對象。 前面介紹過的動態(tài)站點(diǎn)對象 Target 屬性所引用的委托是第一級緩存,它實(shí) 現(xiàn)的處理邏輯是這樣的: /當(dāng)前處理規(guī)則,屬于第 1 級緩存 if( d1 is int && d2 is int) /測試條件 return (int)d1+(int)d2; /滿足測試條件,直接返回一個(gè)表達(dá)式樹 /未命中,則在第 2 級、第 3 級緩存中查找,如果找到了,用找到的結(jié)果更 新第 1 級緩存
19、 return site.Update(site,d1,d2); 如果 3 級緩存中都沒有命中的規(guī)則, 則此動態(tài)站點(diǎn)所關(guān)聯(lián)的調(diào)用站點(diǎn)綁定對 象會嘗試創(chuàng)建一個(gè)新的規(guī)則。 如果創(chuàng)建新規(guī)則失敗, 則由當(dāng)前編程語言(比如 C#) 所提供的默認(rèn)調(diào)用站點(diǎn)綁定對象決定如何處理,通常的作法是拋出一個(gè)異常。 當(dāng)前版本的 DLR 第 2 級緩存了 10 條規(guī)則,第 3 級則緩存了 100 條規(guī)則。 由于 DLR 自身設(shè)計(jì)了一個(gè)“規(guī)則”緩存系統(tǒng),又充分利用了 CLR 所提供的 JIT 緩存(因?yàn)樗袆討B(tài)調(diào)用代碼最終都會轉(zhuǎn)換為 CLR 可以執(zhí)行的 IL 指令, CLR 而 可以緩存這些代碼),使得動態(tài)代碼僅僅在第一次
20、執(zhí)行時(shí)性能較差,后續(xù)的連續(xù) 調(diào)用其性能可以逼近靜態(tài)代碼。 3 C# 4 與動態(tài)語言的集成 由于幾乎所有的編程語言都可以使用抽象語法樹來表達(dá),因此,在理論上 DLR 支持無限多種編程語言間的互操作,在當(dāng)前版本中,可以實(shí)現(xiàn) C#/Visual Basic 與 IronPython 和 IronRuby 的互操作,相信很快會出現(xiàn)其他動態(tài)編程語言 的 DLR 實(shí)現(xiàn)。 一個(gè)有趣的地方是當(dāng)前基于 DLR 實(shí)現(xiàn)的動態(tài)編程語言都以“Iron”開頭,比 如 IronRuby 和 IronPython。 IronPython 的設(shè)計(jì)者、 的架構(gòu)設(shè)計(jì)師 Jim Hugunin DLR 曾經(jīng)在微軟 PDC 2008
21、大會上解釋說主要是為了避免起一個(gè)“Python.NET”或 “Python for .NET”之類“微軟味十足”的名字,才有了“IronPython”。他 強(qiáng)調(diào):“Iron”系列動態(tài)語言將嚴(yán)格遵循動態(tài)語言自身的標(biāo)準(zhǔn)和規(guī)范,尊重這些 動態(tài)語言已有的歷史和積累,不會引入一些僅限于.NET 平臺的新語言特性,并 且這些語言的.NET 實(shí)現(xiàn)保持開源。與此同時(shí),Jim Hugunin 指出 “Iron”系列 語言能很好地與.NET 現(xiàn)有類庫、編程語言和工具集成,并且能“嵌入”到.NET 宿主程序中。 (1)動態(tài)對象通訊協(xié)議 (1)動態(tài)對象通訊協(xié)議 由于各種動態(tài)編程語言之間的特性相差極大, 實(shí)現(xiàn)各語言間的
22、互操作是個(gè)難 題。為此 DLR 采取了一個(gè)聰明的策略,它不去嘗試設(shè)計(jì)一個(gè)“通用的類型系統(tǒng)” (CLR 就是這么干的),而是設(shè)計(jì)了一個(gè)“通用的對象通訊協(xié)議”,規(guī)定所有需要 互操作的動態(tài)對象必須實(shí)現(xiàn) IDynamicMetaObjectProvider 接口,此接口定義了 一個(gè) GetMetaObject()方法, 接收一個(gè)語法樹對象作為參數(shù), 向外界返回一個(gè) “動 態(tài)元數(shù)據(jù)(DynamicMetaObject)”對象: DynamicMetaObject GetMetaObject(Expression parameter); DynamicMetaObject 對象向外界提供了兩個(gè)重要屬性:
23、Restrictions 引用一 組測試條件,Expression 屬性則引用一個(gè)語法樹。這兩個(gè)屬性組合起來就是可 供動態(tài)站點(diǎn)對象緩存的“規(guī)則(Rule)”。 DLR 中的 “動態(tài)站點(diǎn)綁定對象(CallSiteBinder)” 獲取了 DynamicMetaObject 對象之后,它調(diào)用此對象所提供的各個(gè)方法創(chuàng)建“規(guī)則”,讓“動態(tài)站點(diǎn)對象 (CallSite)”的 Target 屬性引用它,完成動態(tài)綁定的工作。 (2)動態(tài)語言集成環(huán)境 (2)動態(tài)語言集成環(huán)境 動態(tài)語言集 為了方便地實(shí)現(xiàn)靜態(tài)編程語言與各種動態(tài)編程語言間的相互集成,DLR 提供 了一整套稱為“通用寄宿(Common Hosting
24、)”的組件,其中包容 ScriptRuntime、 ScriptScope 等類型。 下面我們以 IronPython 為例,介紹如何在 C# 4 開發(fā)的程序中集成動態(tài)編程 語言代碼。 首先需要創(chuàng)建一個(gè) ScriptRuntime 對象,它是一個(gè)最頂層的對象,用于在一 個(gè).NET 應(yīng)用程序域中“嵌入”一個(gè)特定動態(tài)語言的運(yùn)行環(huán)境: ScriptRuntime pythonRuntime = Python.CreateRuntime(); 接著需要創(chuàng)建一個(gè) ScriptEngine 對象,它是動態(tài)語言代碼的執(zhí)行引擎: ScriptEngine engine = pythonRuntime.GetE
25、ngine("py"); ScriptScope 對象類似于 C#中的命名空間, 其中可以通過定義一些變量向動 態(tài)代碼傳入數(shù)據(jù),比如下述代碼將一個(gè) C# 創(chuàng)建的 ExpandoObject 對象傳給 Python 代碼: ScriptScope scope = pythonRuntime.CreateScope(); /C#創(chuàng)建動態(tài)對象 dynamic expando = new ExpandoObject(); expando.Name = "JinXuLiang" /動態(tài)添加一個(gè)字段 /讓 IronPython 接收 C#創(chuàng)建的 Expando 對象 scope.SetVariable("ExpandoObject", expando); string pythonCode = "print ExpandoObject.Name" /IronPython 引擎執(zhí)行 Python 語句 engine.CreateScriptSourceFromString(pythonCode
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 公司月度生日會策劃方案
- 公司春節(jié)返工活動方案
- 公司晚上團(tuán)建活動方案
- 公司相互送福字活動方案
- 公司組織種菜活動方案
- 公司短視頻運(yùn)營策劃方案
- 公司文娛團(tuán)建活動方案
- 公司管理層旅游策劃方案
- 2025年自動化控制技術(shù)人員招聘考試試題及答案
- 拓展任務(wù)-避難場所
- 2025-2030年中國樓宇對講系統(tǒng)行業(yè)市場深度調(diào)研及競爭格局與投資研究報(bào)告
- 暑假提升部編版小學(xué)語文四升五暑假閱讀提升之概括文章中心思想 課件
- 2025年甘肅省隴南市事業(yè)單位招聘247人筆試參考題庫及參考答案詳解1套
- 2025聊城市輔警考試試卷真題
- 2025廣西專業(yè)技術(shù)人員公需科目培訓(xùn)考試答案
- 人工智能概論課件完整版
- 國際學(xué)校六年級數(shù)學(xué)測(英文)
- 標(biāo)識標(biāo)牌的制作與安裝
- 動力站柴油儲罐施工方案
- 注塑車間機(jī)臺日報(bào)表
- 空氣站質(zhì)量控制措施之運(yùn)行維護(hù)
評論
0/150
提交評論