首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 4.0 dynamic 關鍵字深度解析:動態綁定原理、與 var/reflection 對比、效能分析

     編輯:關於C#

dynamic 是什麼?

dynamic 是 C# 4.0 引入的**靜態類型**,但編譯器對其操作**延遲到執行時期**進行綁定。聲明為 dynamic 的變數,編譯時不檢查成員是否存在,執行時透過 DLR (Dynamic Language Runtime) 動態調度。

基本用法


dynamic d = Console.Out;        // 可接受任何物件
d.WriteLine("Hello DLR!");      // 執行時解析 WriteLine 方法
d.NonExistMethod();             // 編譯通過,執行時拋 RuntimeBinderException

dynamic x = 10;
x++; x--;                       // 支援運算子
int i = x;                      // 隱式轉換回靜態類型

dynamic vs var:本質區別

特性vardynamic
類型推斷時機編譯期(初始化時即確定)執行期(每次操作動態綁定)
適用範圍僅區域變數欄位、屬性、參數、返回值、泛型參數
重新賦值不同類型不允許允許
IntelliSense 支援完整無(編譯期類型未知)
性能零開銷有 DLR 快取開銷

dynamic vs 反射:代碼簡潔度對比


// 反射調用 instance.GetName()
var asm = Assembly.GetExecutingAssembly();
var obj = asm.CreateInstance("MyNamespace.MyClass");
var mi = obj.GetType().GetMethod("GetName");
string name = (string)mi.Invoke(obj, null);

// dynamic 調用
dynamic dyn = new MyClass();
string name = dyn.GetName(); // 一行搞定

限制:dynamic **不支援屬性存取**(`dyn.Prop` 會失敗),因屬性編譯為 `get_Prop`/`set_Prop` 方法,DLR 目前不自動映射。需手動呼叫 `dyn.get_Prop()`(但實測仍失敗,建議改用反射或介面)。

效能深度剖析:IL 與 CallSite 快取機制

簡單代碼:


dynamic d = "str";
d.ToString();

編譯器生成(Reflector 反編譯 .NET 4.0 模式):


object d = "str";
if (<>o__SiteContainer0.<>p__Site1 == null)
    <>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(
        new CSharpInvokeMemberBinder(
            CSharpCallFlags.None, "ToString", typeof(Program), null,
            new[] { new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null) }));

<>o__SiteContainer0.<>p__Site1.Target(<>o__SiteContainer0.<>p__Site1, d);

關鍵機制

  1. 裝箱:值類型賦給 dynamic 會發生裝箱(`object d = 5`)。
  2. CallSite 快取:編譯器生成巢狀靜態類 `<>o__SiteContainer0`,靜態欄位 `<>p__Site1` 快取 `CallSite` 委派。
  3. 首次調用慢:第一次呼叫建立 `CallSite`、綁定器、快取;後續直接呼叫 `Target` 委派。
  4. 同一方法多次調用:
    • 迴圈內:共用同一 `CallSite`(快取命中)。
    • 非迴圈連續調用:編譯器可能生成多個 `CallSite`(``, ``...),各自快取,增加記憶體壓力。

效能建議

  • 熱路徑(高頻迴圈、遊戲主迴圈、即時運算)**避免使用 dynamic**。
  • 互操作場景(COM、IronPython、JSON 反序列化、動態 XML)適合使用。
  • 可搭配 `ImpromptuInterface` 庫,將 dynamic 物件強類型化為介面,兼顧動態與靜態優勢。

總結

dynamic 讓 C# 具備動態語言特性,極大簡化 COM 互操作、動態語言互通、晚期綁定場景代碼。但需理解其**執行時綁定、CallSite 快取、裝箱開銷**本質,在效能敏感場合謹慎使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved