C# 動(dòng)態(tài)查找
如前所述,var關(guān)鍵字本身并不是一個(gè)類型,所以并沒有違反C#的“強(qiáng)類型化”方法論。但從C#4開始,—些地方變得沒那么死板。C#4引入了“動(dòng)態(tài)變量”的概念,顧名思義,動(dòng)態(tài)變量是類型可變的變量。
引入動(dòng)態(tài)變量的主要目的是在許多情況下,希望使用C#處理另一種語言創(chuàng)建的對(duì)象。這包括與舊技術(shù)的交互操作,例如Component Object Model(COM),也包括處理動(dòng)態(tài)語言,例如JavaScript、Python和Ruby,這里不詳細(xì)討論其實(shí)現(xiàn)細(xì)節(jié),只需要知道,過去使用C#訪問這些語言所創(chuàng)建的對(duì)象的方法和屬性需要用到笨拙的語法。例如,假定代碼從JavaScript中獲得一個(gè)帶Add()方法的對(duì)象,該方法把兩個(gè)數(shù)字加在一起,如果沒有動(dòng)態(tài)查找功能,調(diào)用這個(gè)方法的代碼就如下所示:
ScriptObject jsObj = SomeMethodThatGetsTheObject();
int sum = Convert .ToInt32 (jsObj.Invoke("Add_", 2, 3));
ScriptObject類型(這里不深入探討)提供了一種訪問JavaScript對(duì)象的方式,但仍不能執(zhí)行如下操作:
int sum = jsObj.Add(2, 3);
動(dòng)態(tài)查找功能改變了這一切,它允許編寫上述代碼,但如下面幾節(jié)所述,這個(gè)功能是有代價(jià)的。
另一個(gè)可使用動(dòng)態(tài)查找功能的情形是處理未知類型的c#對(duì)象D這聽起來似乎很古怪,但這種情形出現(xiàn)的次數(shù)比我們想象得多。如果需要編寫一璧泛型代碼來處理接收的各種輸入,這也是一項(xiàng)重要功能。處理這種情形的“舊”方法稱為“反射(reflection)”,它涉及使用類型信息來訪問類型和成員?前一章使用了簡(jiǎn)單的反射來訪問與類型關(guān)聯(lián)的特性。使用反射訪問類型成員(如方法}的語法非常類似于上述代碼中訪問JavaScript對(duì)象的語法,也非常麻煩。
在后臺(tái),動(dòng)態(tài)查找功能由Dynamic Language Runtime(動(dòng)態(tài)語言運(yùn)行庫,DLR)支持。與CLR—樣,DLR是.NET 4.7的一部分。DLR的精確描述及其如何簡(jiǎn)化交互操作超出了本書的討論范圍,這里僅對(duì)如何在C#中使用它感興趣。有關(guān) DLR 的更多內(nèi)容,可以參閱 https:〃docs.microsoft.com/en-us/dotnet/fi'amework/reflection-and-codedom/dynam ic-I anguage-runtime-overview。
動(dòng)態(tài)類型
C#4引入了 dynamic關(guān)鍵字,以用于定義變量。例如:
dynamic myDynamicVar;
與前面介紹的var關(guān)鍵字不同,的確存在動(dòng)態(tài)類型,所以在聲明myDynamicVar時(shí),不必初始化它的值。
一旦有了動(dòng)態(tài)變量,就可以繼續(xù)訪問其成員(這里沒有列出實(shí)際獲取變量值的代碼)。
myDynamicVar.DoSomething {"With this !");
無論myDynamicVar實(shí)際包含什么值,這行代碼都會(huì)編譯。但是,如果所請(qǐng)求的成員不存在,在執(zhí)行這行代碼時(shí)會(huì)生成一個(gè)RuntimeBinderException類型的異常。
實(shí)際上,像這樣的代碼提供了一個(gè)應(yīng)在運(yùn)行期間應(yīng)用的“處方”。檢查myDynamicVar的值,找到帶一個(gè)字符串參數(shù)的DoSomething()方法,并在需耍時(shí)調(diào)用它。
點(diǎn)擊加載更多評(píng)論>>