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

來源:互聯網
上載者:User

廢話不多說,直接開始。先看程式:

Code
1class Program
2{
3 static void Main(string[] args)
4{
5dynamic foo1 = new Foo();
6        foo1.Do1();
7        foo1.Do2();
8foo1.KissFanweixiao();
9    }
10}
11
12public class Foo
13{
14 public void Do1() { Console.WriteLine("fanweixiao calls do1"); }
15 public void Do2() { Console.WriteLine("fanweixiao calls do2"); }
16}

這段代碼在vs2010中可以編譯通過。但是在啟動並執行時候會報錯。這是必然,KissFanweixiao()這個方法無中生有嘛。

這裡注意到這是個RuntimeBinderException,而內容是不能找到KissFanweixiao的符號。

dynamic這個關鍵字看起來跟3.0增加的var很像,但是從IL的角度上來看,就是天壤之別了,畢竟var是編譯時間就能確定的東西,而dynamic追求的就是在運行時再決定究竟是個什麼東西。我們還是先注釋掉foo1.KissFanweixiao();這一句,使程式可以正常運行,然後看ILDASM的結果:

多出一個<Main>o__SiteContainer0類,這個類下的<>p__Site1...和<>p__Site2...對應著Do1()和Do2()兩個方法的Invoke。再細看此時的Main函數:

Code
.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// Code size       139 (0x8b)
.maxstack 7
.locals init ([0] object foo1)
IL_0000: newobj instance void LearnCSharp4.Foo::.ctor()
IL_0005: stloc.0
IL_0006: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
IL_000b: brtrue.s   IL_0033
IL_000d: call class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder::GetInstance()
IL_0012: ldc.i4.0
IL_0013: ldc.i4.0
IL_0014: ldstr "Do1"
IL_0019: ldtoken    [mscorlib]System.Object
IL_001e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0023: ldnull
IL_0024: newobj instance void [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpCallPayload::.ctor(class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder,
bool,
bool,
string,
class [mscorlib]System.Type,
class [mscorlib]System.Type[])
IL_0029: call class [System.Core]System.Scripting.Actions.CallSite`1<!0> class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Create(class [System.Core]System.Scripting.Actions.CallSiteBinder)
IL_002e: stsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
IL_0033: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
IL_0038: ldfld      !0 class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Target
IL_003d: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
IL_0042: ldloc.0
IL_0043: callvirt instance void class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>::Invoke(!0,
                                                                                                                                             !1)
IL_0048: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
IL_004d: brtrue.s   IL_0075
IL_004f: call class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder::GetInstance()
IL_0054: ldc.i4.0
IL_0055: ldc.i4.0
IL_0056: ldstr "Do2"
IL_005b: ldtoken    [mscorlib]System.Object
IL_0060: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0065: ldnull
IL_0066: newobj instance void [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpCallPayload::.ctor(class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder,
bool,
bool,
string,
class [mscorlib]System.Type,
class [mscorlib]System.Type[])
IL_006b: call class [System.Core]System.Scripting.Actions.CallSite`1<!0> class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Create(class [System.Core]System.Scripting.Actions.CallSiteBinder)
IL_0070: stsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
IL_0075: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
IL_007a: ldfld      !0 class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Target
IL_007f: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
IL_0084: ldloc.0
IL_0085: callvirt instance void class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>::Invoke(!0,
                                                                                                                                             !1)
IL_008a: ret
} // end of method Program::Main

如果是var或Foo的話直接這樣就完事了:

Code
1 IL_0000: newobj instance void LearnCSharp4.Foo::.ctor()
2 IL_0005: stloc.0
3 IL_0006: ldloc.0
4 IL_0007: callvirt instance void LearnCSharp4.Foo::Do1()
5 IL_000c: ldloc.0
6 IL_000d: callvirt instance void LearnCSharp4.Foo::Do2()
7 IL_0012: ret

OK,看出不同來了。然後取消掉對foo.KissFanweixiao();的注釋,再編譯,再用ILDASM看,Do1()和KissFanWeixiao()的地位應該是一樣的——因為dynamic與編譯時間無關嘛(好像是廢話...但是這點很重要)。我們再看一眼有三個方法後的MSIL:

Code
1.method private hidebysig static void  Main(string[] args) cil managed
2{
3 .entrypoint
4 // Code size       205 (0xcd)
5 .maxstack 7
6 .locals init ([0] object foo1)
7 IL_0000: newobj instance void LearnCSharp4.Foo::.ctor()
8 IL_0005: stloc.0
9 IL_0006: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
10 IL_000b: brtrue.s   IL_0033
11 IL_000d: call class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder::GetInstance()
12 IL_0012: ldc.i4.0
13 IL_0013: ldc.i4.0
14 IL_0014: ldstr "Do1"
15 IL_0019: ldtoken    [mscorlib]System.Object
16 IL_001e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
17 IL_0023: ldnull
18 IL_0024: newobj instance void [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpCallPayload::.ctor(class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder,
19 bool,
20 bool,
21 string,
22 class [mscorlib]System.Type,
23 class [mscorlib]System.Type[])
24 IL_0029: call class [System.Core]System.Scripting.Actions.CallSite`1<!0> class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Create(class [System.Core]System.Scripting.Actions.CallSiteBinder)
25 IL_002e: stsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
26 IL_0033: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
27 IL_0038: ldfld      !0 class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Target
28 IL_003d: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site1'
29 IL_0042: ldloc.0
30 IL_0043: callvirt instance void class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>::Invoke(!0,
31                                                                                                                                             !1)
32 IL_0048: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
33 IL_004d: brtrue.s   IL_0075
34 IL_004f: call class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder::GetInstance()
35 IL_0054: ldc.i4.0
36 IL_0055: ldc.i4.0
37 IL_0056: ldstr "Do2"
38 IL_005b: ldtoken    [mscorlib]System.Object
39 IL_0060: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
40 IL_0065: ldnull
41 IL_0066: newobj instance void [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpCallPayload::.ctor(class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder,
42 bool,
43 bool,
44 string,
45 class [mscorlib]System.Type,
46 class [mscorlib]System.Type[])
47 IL_006b: call class [System.Core]System.Scripting.Actions.CallSite`1<!0> class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Create(class [System.Core]System.Scripting.Actions.CallSiteBinder)
48 IL_0070: stsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
49 IL_0075: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
50 IL_007a: ldfld      !0 class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Target
51 IL_007f: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site2'
52 IL_0084: ldloc.0
53 IL_0085: callvirt instance void class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>::Invoke(!0,
54                                                                                                                                             !1)
55 IL_008a: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site3'
56 IL_008f: brtrue.s   IL_00b7
57 IL_0091: call class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder::GetInstance()
58 IL_0096: ldc.i4.0
59 IL_0097: ldc.i4.0
60 IL_0098: ldstr "KissFanweixiao"
61 IL_009d: ldtoken    [mscorlib]System.Object
62 IL_00a2: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
63 IL_00a7: ldnull
64 IL_00a8: newobj instance void [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpCallPayload::.ctor(class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder,
65 bool,
66 bool,
67 string,
68 class [mscorlib]System.Type,
69 class [mscorlib]System.Type[])
70 IL_00ad: call class [System.Core]System.Scripting.Actions.CallSite`1<!0> class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Create(class [System.Core]System.Scripting.Actions.CallSiteBinder)
71 IL_00b2: stsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site3'
72 IL_00b7: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site3'
73 IL_00bc: ldfld      !0 class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>>::Target
74 IL_00c1: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>> LearnCSharp4.Program/'<Main>o__SiteContainer0'::'<>p__Site3'
75 IL_00c6: ldloc.0
76 IL_00c7: callvirt instance void class [System.Core]System.Action`2<class [System.Core]System.Scripting.Actions.CallSite,object>::Invoke(!0,
77                                                                                                                                             !1)
78 IL_00cc: ret
79} // end of method Program::Main

如果不喜歡看MSIL的話可以這樣看:

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__Site1, foo1);
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}

本文旨在為不方便下載和使用vs2010虛擬機器朋友幫個忙.

(在後台編輯的時候報stack overflow的問題...無法提交...)

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.