使用動態型別 (C# 程式設計手冊)

Visual C# 2010 引進一種新型別 dynamic。 此型別是靜態型別,但型別為 dynamic 的物件會略過靜態型別檢查。 在大部分的情況下,其運作會像是具有 object 型別。 在編譯時期,會假設型別為 dynamic 的項目能夠支援所有作業。 因此,您無須考慮物件是從 COM API、動態語言 (例如 IronPython)、HTML 文件物件模型 (DOM)、反映或是程式其他地方取得其值。 不過,如果程式碼無效,則會在執行階段攔截到錯誤。

例如,如果下列程式碼中的執行個體方法 exampleMethod1 只有一個參數,則編譯器會將第一個方法呼叫 ec.exampleMethod1(10, 4) 視同無效,因為呼叫中包含兩個引數。 此呼叫會造成編譯器錯誤。 編譯器不會檢查第二個方法呼叫 dynamic_ec.exampleMethod1(10, 4),因為 dynamic_ec 的型別是 dynamic。 因此,不會報告編譯器錯誤。 但是這項錯誤並不是永遠不會被發現, 執行階段會攔截到錯誤,並產生執行階段例外狀況。

static void Main(string[] args)
{
    ExampleClass ec = new ExampleClass();
    // The following line causes a compiler error if exampleMethod1 has only
    // one parameter.
    //ec.exampleMethod1(10, 4);

    dynamic dynamic_ec = new ExampleClass();
    // The following line is not identified as an error by the
    // compiler, but it causes a run-time exception.
    dynamic_ec.exampleMethod1(10, 4);

    // The following calls also do not cause compiler errors, whether 
    // appropriate methods exist or not.
    dynamic_ec.someMethod("some argument", 7, null);
    dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
    public ExampleClass() { }
    public ExampleClass(int v) { }

    public void exampleMethod1(int i) { }

    public void exampleMethod2(string str) { }
}

上述範例中的編譯器角色,就是將每個陳述式應該對型別為 dynamic 的物件或運算式所進行之動作的相關資訊包裝在一起。 到了執行階段會檢驗這些儲存資訊,如果有任何陳述式是無效的,便會產生執行階段例外狀況。

大部分動態作業的結果就是其本身 (dynamic)。 例如,在下列範例中,如果您將滑鼠指標停在 testSum 的使用用途上,IntelliSense 會顯示型別 [(區域變數) dynamic testSum]。

dynamic d = 1;
var testSum = d + 3;
// Rest the mouse pointer over testSum in the following statement.
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,或如果方法呼叫的接收端是型別 dynamic,則多載解析會發生在執行階段,而非編譯時期。 在下列範例中,如果唯一可存取的 exampleMethod2 方法被定義為接受字串引數,則將 d1 做為引數傳送不會造成編譯器錯誤,但會引起執行階段例外狀況。 多載解析在執行階段會失敗,因為 d1 的執行階段型別是 int,但 exampleMethod2 需要的是字串。

// Valid.
ec.exampleMethod2("a string");

// The following statement does not cause a compiler error, even though ec is not
// dynamic. A run-time exception is raised because the run-time type of d1 is int.
ec.exampleMethod2(d1);
// The following statement does cause a compiler error.
//ec.exampleMethod2(7);

Dynamic Language Runtime

Dynamic Language Runtime (DLR) 是 .NET Framework 4 中的新 API。 它提供的基礎結構支援 C# 中的 dynamic 型別,也支援實作 IronPython 和 IronRuby 之類的動態程式設計語言。 如需 DLR 的詳細資訊,請參閱 Dynamic Language Runtime 概觀

COM Interop

Visual C# 2010 包含數種可改善與 COM API (例如 Office Automation API) 相互操作之經驗的功能。 其中有一項改善功能是使用 dynamic 型別,另一項是使用具名和選擇性引數

許多 COM 方法都允許針對引數型別和傳回型別進行變化,方法是將型別指定為 object。 但這需要對值進行明確轉型,才能與 C# 中的強型別變數配合使用。 如果您使用 /link (C# 編譯器選項) 選項進行編譯,則採用 dynamic 型別就能讓您將 COM 簽章中的 object 項目視同 dynamic 型別,如此就不用進行轉型。 例如,下列陳述式將比較使用 dynamic 型別和不使用 dynamic 型別存取 Microsoft Office Excel 試算表中的儲存格。

// Before the introduction of dynamic.
((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name";
Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];
// After the introduction of dynamic, the access to the Value property and
// the conversion to Excel.Range are handled by the run-time COM binder.
excelApp.Cells[1, 1].Value = "Name";
Excel.Range range2010 = excelApp.Cells[1, 1];

相關主題

標題

說明

dynamic (C# 參考)

說明 dynamic 關鍵字的使用方法。

Dynamic Language Runtime 概觀

提供 DLR 概觀,DLR 是在 Common Language Runtime (CLR) 中加入了一組動態語言服務的執行階段環境。

逐步解說:建立和使用動態物件 (C# 和 Visual Basic)

針對建立自訂動態物件以及建立專案用於存取 IronPython 程式庫,提供逐步指示。

HOW TO:使用 Visual C# 2010 功能存取 Office Interop 物件 (C# 程式設計手冊)

說明如何使用具名和選擇性引數、dynamic 型別,以及其他可簡化 Office API 物件存取方式的增強功能,來建立專案。