(資料圖片僅供參考)
這個var和dynamic都是不確定的初始化類型,但是這兩個本質上的不同。不同在哪兒呢?var編譯階段確定類型,dynamic運行時階段確定類型。這種說法對不對呢?本篇看下,文章原文地址:在這里
概括以下詳細敘述下這兩個(var,dynamic)上下文關鍵字的不同點。1.例子
static void Main(string[] args){ var a = 0x10; dynamic b = 0x10;}
var其實在你設置它的變量a的值的那一刻起,它的類型就確定了。這點你可以在VS里,在var上面查看定義,就可以看到例子里面a的類型就是Int32。如果你把變量a賦值為字符串類型,那么它變量a的類型就是string。嚴格來說還沒到編譯階段,在編譯器VS里面就被識別了類型。而dynamic則不同,它類似于public,static。無法查看其實際類型,但是這里注意了dynamic和var同稱之為:上下文關鍵字(官方說法是在代碼中提供特殊含義)。也就是說它們兩個在C#里面嚴格來說都是關鍵字。只不過運作模式不同而已。
2.IL Code
.method private hidebysig static void Main(string[] args) cil managed{ .locals init (int32 V_0, object V_1) IL_0000: nop IL_0001: ldc.i4.s 16 IL_0003: stloc.0 IL_0004: ldc.i4.s 16 IL_0006: box [System.Runtime]System.Int32 IL_000b: stloc.1 IL_000c: ret} // end of method Program::Main
在IL里面,var的操作模式是:將0x10(十進制的16)推送到堆上,然后從堆里面取出來賦值給a。dynamic的操作模式是:將0x10推送到堆上,然后從堆上取出來作為參數傳遞給box函數。這里可以看到很明顯的不同。當然IL依然遠遠不夠。所以下面我們上JIT。
3.ASM Code
var a=0x1000007FF9FC1A76DC mov dword ptr [rbp+3Ch],10h dynamic b=0x1000007FF9FC1A76E3 mov rcx,7FF9FC10E8D0h 00007FF9FC1A76ED call CORINFO_HELP_NEWSFAST (07FFA5BCA0000h) 00007FF9FC1A76F2 mov qword ptr [rbp+28h],rax 00007FF9FC1A76F6 mov rax,qword ptr [rbp+28h] 00007FF9FC1A76FA mov dword ptr [rax+8],10h 00007FF9FC1A7701 mov rax,qword ptr [rbp+28h] 00007FF9FC1A7705 mov qword ptr [rbp+30h],rax
可以看到dynamic的code遠比var的code夸張,而且性能也是成問題的。它這里調用了CORINFO_HELP_NEWSFAST,實際上是進行了一個裝箱,也就是IL的box,運行時里面的JIT_New。先傳入參數,然后返回裝箱后的對象地址也就是MethodTable,最后把0x10放入到&Methodtable+8地方。而var只是直接把0x10放入到棧。這么看來,如果有性能需求,還是建議var,而慎用dynamic。
4.總結:var和dynamic的不同點。1.var被rosyln編譯前就確定了類型,而dynamic則是在CLR(這里更嚴格點應該說是在JIT)里面確定。2.var只是一個簡單的值,而dynamic則被實例化成了一個對象,它的變量值是它對象的字段3.var的性能遠遠大于dynamic的性能。
結尾作者:江湖評談歡迎關注我的公眾號:江湖評談(jianghupt),文章首發。