c#4.0新特性之一: Dynamic Lookup (2)

來源:互聯網
上載者:User

我們分析一下用Reflector看到的東西:

Code
 1private static void Main(string[] args)
 2{
 3     object  foo1 = new Foo();
 4    if (<Main>o__ SiteContainer0.<>p__ Site1 == null)
 5    {
 6        <Main>o__SiteContainer0.<>p__Site1 =  CallSite<Action<CallSite, object>>. Create(new CSharpCallPayload(Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetInstance(), false, false, " Do1",  typeof(object ), null));
 7    }
 8    <Main>o__SiteContainer0.<>p__Site1. Target(<Main>o__SiteContainer0.<>p__ Site1foo1);
 9    if (<Main>o__SiteContainer0.<>p__Site2 == null)
10    {
11        <Main>o__SiteContainer0.<>p__Site2 = CallSite<Action<CallSite, object>>.Create(new CSharpCallPayload(Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetInstance(), false, false, "Do2", typeof(object), null));
12    }
13    <Main>o__SiteContainer0.<>p__Site2.Target(<Main>o__SiteContainer0.<>p__Site2, foo1);
14    if (<Main>o__SiteContainer0.<>p__Site3 == null)
15    {
16        <Main>o__SiteContainer0.<>p__Site3 = CallSite<Action<CallSite, object>>.Create(new CSharpCallPayload(Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetInstance(), false, false, "KissFanweixiao", typeof(object), null));
17    }
18    <Main>o__SiteContainer0.<>p__Site3.Target(<Main>o__SiteContainer0.<>p__Site3, foo1);
19}

 

首先,編譯器產生了__SiteContainer0的本地變數來儲存我們的CallSite的內容,然後我們注意到test已經是object類型。由此看來這不能算是什麼真正的“動態類型”,只不過算是個“協助方法”罷了。

接下來代碼會檢查這個CallSite是否是null,如果是,就是用CallSite.Create並且傳遞一個CSharpCallPayload的對象作為參數,這個對象儲存了所有我們將要去調用的方法的資訊。如果這個CallSite不為null,就把這個方法的所有的所有內“附著”到foo這個對象上了。

編譯器就是做了這兩步,實現了這種動態功能。

以上內容來自Justin Etheredge的blog,該blog的後文還比較了dynamic的效率問題,經過他的測試,使用var和使用dynamic造成的天壤之別使其效能也有天壤之別,6ms:2106ms。但是我剛看到這測試的時候就覺得不太恰當,如果您自己運行一下dynamic的程式就知道一啟動的時候總以為程式出問題了一點反應都沒有,過了一會才出結果,也就是runtime上第一次handle這些東東是要有較高時間消耗的,但是這個情況只有一開始載入的時候才會出現,所以比較效率的這組數字不能說的太準確,更何況兩者不是幹同一個活的,一個是八路,一個是地下工作者,沒法比。不過Justin兄弟剛又更新了一篇blog,又重新分析了這個測試,並增加了測試的case,還是挺不錯的,值得一看。

Dynamic lookup特性使我們可以使用一種統一的方式動態invoke其他資源,通過它,我們的對象不需要關心是來在COM,IronPython還是reflection,我們只需要將需要的東西apply給它(熟悉javascript的朋友看到apply就明白dynamic的思想了吧),在runtime時.net自動幫我們搞定剩下的工作。

這給我們的開發給予了巨大的靈活性,但是dynamic object在編譯時間是閉著眼睛過去的,所以對於運行時能否正確通過,我們就比較麻煩了。

從上面的reflect後的代碼我們能看到dynamic類型可以被認為是一個特殊版本的object——只是標記了這個對象能被動態使用,任何對象都可以被顯時的轉換為dynamic類型。相反的,還有一種assignment conversion(賦值轉換)可以將dynamic類型轉換為其他類型:

dynamic d = 7; // implicit conversion
int i = d; // assignment conversion

當然,不只方法可以這麼用,欄位、屬性、索引器、操作符和委託都可以dynamic:

dynamic d = GetDynamicObject(…);
d.M(7); // calling methods
d.f = d.P; // getting and settings fields and properties
d["one"] = d["two"]; // getting and setting through indexers
int i = d + 3; // calling operators
string s = d(5,7); // invoking as a delegate

對於運行時的lookup,dynamic機制是根據它的目標對象來確定的,就是說new的是啥玩意,就通過這個東東來確定怎麼lookup,對待COM是通過IDispatch,對於Dynamic對象是通過IDynamicObject,對於標準的.net對象就是用反射,這些內容從微軟的官方文檔裡就能很容易看明白。

拿微軟的一個例子來說一下dynamic的一個應用:

我們寫一個IronPython的方法:

Code
1def welcome(name):
2    return "Hello '" + name + "' from fanweixiao" 

存為helloworld.py

然後用ScriptRuntime py = Python.CreateRuntime();建立IronPython的運行環境,用dynamic helloworld = py.UseFile("helloworld.py");來建立動態類型helloworld,就可以使用helloworld.welcome("cnblogs guy");來列印出結果來了。

很爽吧?做silverlight的也不用死盯著一門語言不放了。

C#與Java的攀比從2.0的泛型開始逐漸佔據上風,到了3.0時代的LINQ,再到4.0時代的Dynamic,不得不說優勢的顯著。但是技術終歸是個工具,工具生來就是被利用的,我同意馮大輝的觀點,使用現有技術足夠做好現在市場需要的需求了。不管開發速度有多快,產品架構有多好,我們還是應該多離開code去看看我們的使用者究竟在想什麼。不要除了coding就是用“我在做伏地挺身”來回答使用者的問題。

c#4.0新特性之一: Dynamic Lookup (1)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.