C# 4 引入了一個新類型 dynamic
。 該類型是一種靜態類型,但類型爲 dynamic
的對象會跳過靜態類型檢查。 大多數狀況下,該對象就像具備類型 object
同樣。 在編譯時,將假定類型化爲 dynamic
的元素支持任何操做。 所以,沒必要考慮對象是從 COM API、從動態語言(例如 IronPython)、從 HTML 文檔對象模型 (DOM)、從反射仍是從程序中的其餘位置獲取本身的值。 可是,若是代碼無效,則在運行時會捕獲到錯誤。 html
在經過 dynamic
類型實現的操做中,該類型的做用是繞過編譯時類型檢查。 改成在運行時解析這些操做。 dynamic
類型簡化了對 COM API(例如 Office Automation API)、動態 API(例如 IronPython 庫)和 HTML 文檔對象模型 (DOM) 的訪問。編程
在大多數狀況下,dynamic
類型與 object
類型的行爲相似。 可是,若是操做包含 dynamic
類型的表達式,那麼不會經過編譯器對該操做進行解析或類型檢查。 編譯器將有關該操做信息打包在一塊兒,以後這些信息會用於在運行時評估操做。 在此過程當中,dynamic
類型的變量會編譯爲 object
類型的變量。 所以,dynamic
類型只在編譯時存在,在運行時則不存在。app
下面的示例將 dynamic
類型的變量與 object
類型的變量進行對比。 若要在編譯時驗證每一個變量的類型,請將鼠標指針放在 WriteLine
語句中的 dyn
或 obj
上。 IntelliSense 對 dyn
顯示「dynamic」 ,對 obj
顯示「object」 。dom
class Program { static void Main(string[] args) { dynamic dyn = 1; object obj = 1; System.Console.WriteLine(dyn.GetType()); System.Console.WriteLine(obj.GetType()); } }
輸出結果:編程語言
若要查看編譯時 dyn
與 obj
之間的區別,請在前面示例的聲明和 WriteLine
語句之間添加下列兩行:ide
dyn = dyn + 3; obj = obj + 3;
嘗試在表達式 obj + 3
中添加整數和對象時,將報告編譯器錯誤。 可是,對於 dyn + 3
,不會報告任何錯誤。 在編譯時不會檢查包含 dyn
的表達式,緣由是 dyn
的類型爲 dynamic
。函數
dynamic
關鍵字能夠直接出現,也能夠做爲構造類型的組件在下列狀況中出現:ui
在聲明中,做爲屬性、字段、索引器、參數、返回值、本地變量或類型約束的類型。下面的類定義在多個不一樣的聲明中使用 dynamic
。spa
class ExampleClass { // 動態字段 static dynamic field; // 動態屬性 dynamic prop { get; set; } // 動態返回類型和動態類型參數 public dynamic exampleMethod(dynamic d) { // 局部動態變量 dynamic local = "Local variable"; int two = 2; if (d is int) { return local; } else { return two; } } }
在顯式類型轉換中,做爲轉換的目標類型。指針
static void convertToDynamic() { dynamic d; int i = 20; d = (dynamic)i; Console.WriteLine(d); string s = "Example string."; d = (dynamic)s; Console.WriteLine(d); DateTime dt = DateTime.Today; d = (dynamic)dt; Console.WriteLine(d); } // 輸出結果: // 20 // Example string. // 7/25/2018 12:00:00 AM
is
運算符或 as
運算符右側),或者用做構造類型中 typeof
的參數。 例如,能夠在下列表達式中使用 dynamic
。int i = 8; dynamic d; // 使用 is 操做符 // 在此處動態類型和object類似,The dynamic type behaves like object。除非 somevar 的值爲 null ,不然如下表達式將返回true if (someVar is dynamic) { } // 使用 as 操做符 d = i as dynamic; // 使用typeof, 做爲構造類型的一部分 Console.WriteLine(typeof(List<dynamic>)); // 如下語句致使編譯器錯誤 //Console.WriteLine(typeof(dynamic));
dynamic
。 Main
方法也將編譯時類型檢查與運行時類型檢查進行了對比。
using System; namespace DynamicExamples { class Program { static void Main(string[] args) { ExampleClass ec = new ExampleClass(); Console.WriteLine(ec.exampleMethod(10)); Console.WriteLine(ec.exampleMethod("value")); // 下面的語句會引起編譯器異常。由於 exampleMethod 方法僅包含一個參數 //Console.WriteLine(ec.exampleMethod(10, 4)); dynamic dynamic_ec = new ExampleClass(); Console.WriteLine(dynamic_ec.exampleMethod(10)); // 由於 dynamic_ec 是 dynamic 類型, 下面的調用(傳遞了2個參數)不會引起編譯器異常。 // 可是在運行時會引起異常。 //Console.WriteLine(dynamic_ec.exampleMethod(10, 4)); } } class ExampleClass { static dynamic field; dynamic prop { get; set; } public dynamic exampleMethod(dynamic d) { dynamic local = "Local variable"; int two = 2; if (d is int) { return local; } else { return two; } } } } // 輸出結果: // Local variable // 2 // Local variable
以上示例中,編譯器的做用是將有關每一個語句的預期做用的信息一塊兒打包到類型化爲 dynamic
的對象或表達式。 在運行時,將對存儲的信息進行檢查,而且任何無效的語句都將致使運行時異常。
大多數動態操做的結果是其自己 dynamic
。 例如,若是將鼠標指針放在如下示例中使用的 testSum
上,則 IntelliSense 將顯示類型「(局部變量)dynamic testSum」 。
dynamic d = 1; var testSum = d + 3; System.Console.WriteLine(testSum);
結果不爲 dynamic
的操做包括:
dynamic
到另外一種類型的轉換。dynamic
的自變量的構造函數調用。例如,如下聲明中 testInstance
的類型爲 ExampleClass
,而不是 dynamic
:
var testInstance = new ExampleClass(d);
動態對象和其餘類型之間的轉換很是簡單。 這樣,開發人員將可以在動態行爲和非動態行爲之間切換。
任何對象均可隱式轉換爲動態類型,如如下示例所示。
dynamic d1 = 7; dynamic d2 = "a string"; dynamic d3 = System.DateTime.Today; dynamic d4 = System.Diagnostics.Process.GetProcesses();
反之,隱式轉換也可動態地應用於類型爲 dynamic
的任何表達式。
int i = d1; string str = d2; DateTime dt = d3; System.Diagnostics.Process[] procs = d4;
dynamic
,或者方法調用的接收方的類型爲 dynamic
,則會在運行時(而不是在編譯時)進行重載決策。 在如下示例中,若是惟一可訪問的 exampleMethod2
方法定義爲接受字符串參數,則將 d1
做爲參數發送不會致使編譯器錯誤,但卻會致使運行時異常。 重載決策之因此會在運行時失敗,是由於 d1
的運行時類型爲 int
,而 exampleMethod2
要求爲字符串。
ec.exampleMethod2("a string"); ec.exampleMethod2(d1);
dynamic
類型的基礎結構,還提供了 IronPython 和 IronRuby 等動態編程語言的實現。 有關 DLR 的詳細信息,請參閱動態語言運行時概述。
C# 4 包括若干功能,這些功能改善了與 COM API(例如 Office 自動化 API)的互操做體驗。 這些改進之處包括 dynamic
類型以及命名參數和可選參數的用法。
經過將類型指定爲 object
,許多 COM 方法都容許參數類型和返回類型發生變化。 這樣,就必須顯式強制轉換值,以便與 C# 中的強類型變量保持協調。 若是使用 /link(C# 編譯器選項)選項進行編譯,則能夠經過引入 dynamic
類型將 COM 簽名中出現的 object
看做是 dynamic
類型,從而避免大量的強制轉換。 例如,如下語句對比了在使用 dynamic
類型和不使用 dynamic
類型的狀況下如何訪問 Microsoft Office Excel 電子表格中的單元格。
// 引入動態以前 ((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name"; Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];
// 在引入 dynamic 以後,對 value 屬性的訪問以及到 excel.range 的轉換將由運行時 COM 綁定器處理 excelApp.Cells[1, 1].Value = "Name"; Excel.Range range2010 = excelApp.Cells[1, 1];
Title | 說明 |
---|---|
dynamic | 描述 dynamic 關鍵字的用法。 |
動態語言運行時概述 | 提供有關 DLR 的概述,DLR 是一種運行時環境,它將一組適用於動態語言的服務添加到公共語言運行時 (CLR)。 |
演練:建立和使用動態對象 | 提供有關如何建立自定義動態對象以及建立訪問 IronPython 庫的對象的分步說明。 |
如何:經過使用 Visual C# 功能訪問 Office 互操做對象 | 演示如何建立一個項目,該項目使用命名參數和可選參數、dynamic 類型以及可簡化對 Office API 對象的訪問的其餘加強功能。 |