本文章是由機器翻譯。

技術最前線

使用 C# 4.0 的動態關鍵字

Dino Esposito

引入的靜態型別檢查表示記錄中的程式語言的重要里程碑。在 1970s年語言 (例如 Pascal 命名法和 C 會啟動強制執行靜態型別和強式型別檢查。與靜態型別檢查,編譯器將會產生無法通過適當型別的方法引數的任何呼叫發生錯誤。同樣地,您應該預期編譯器錯誤,如果您嘗試在型別執行個體上呼叫遺漏的方法。

往前推入相反方法其他語言 — 動態型別檢查 — 多年來已經走。動態型別檢查 contradicts 變數的型別必須是靜態地決定在編譯時期,和變數是在範圍中時,永遠不可以變更的想法。但是,注意動態型別檢查 doesn’t 授予批發自由混合假裝它們 ’re 相同的型別。比方說即使有了動態型別檢查,您仍然 can’t 新增布林 (Boolean) 值為整數。與動態型別檢查不同的是核取發生於程式執行而不是編譯的時機。

以靜態方式鍵入或是以動態方式鍵入

視覺化 Studio 2010 和 C# 4.0 提供一個新的關鍵字,動態,可讓動態鍵入什麼傳統上已被靜態地具型別的語言。之前投擲到動態方面的 C# 4.0,但是,我們需要取得一些基本的術語向下。

let’s 定義變數為限制為特定型別的值的儲存位置。接下來,let’s 指定靜態型別語言的四個基本屬性:

  • 每個運算式是類型的在編譯時間得知。
  • 變數僅限於在編譯時間得知的型別。
  • 編譯器可以保證上工作分派到的變數的運算式的型別限制符合在變數上的限制。
  • 多載解析如 [語意分析] 工作發生編譯時期,而且結果確定到組件。

動態語言有相反的屬性。並非每個運算式是已知的型別在編譯時間,也不是每個變數。儲存體限制如果有任何,在執行階段檢查,略過在編譯時間。只在執行階段發生語意分析。

以靜態型別的語言不會讓您進行某些作業動態。轉換運算子存在,因此您可以嘗試為執行階段作業的型別轉換。轉換是將程式程式碼的一部份,並且您可以合併彙算語意的轉型運算子,作為 「 動態地檢查這種轉換在執行階段的有效性 」 表示。

不過,關於屬性,例如動態和靜態 (或或許是強式和弱式):今天它們更能套用到比要整個語言的程式設計語言的個別功能。

let’s 簡短地考慮 Python 及 PHP。兩者都是動態語言,讓您使用變數,並允許執行階段環境,以找出實際儲存在它的型別。但與 PHP 您可以儲存,說,整數和在相同範圍中相同的變數中的字串。在這方面 (例如 JavaScript) 的 PHP 是 weakly 具型別、 動態語言。

另一方面,Python 提供您要設定一個變數使它更強型別類型只有一個機會。以動態方式可以將型別指派給變數並有執行階段推斷從指派的值。之後的但是,不允許您該變數中儲存不當型別的任何值。

在 C# 中的動態型別

C# 4.0 的功能可以讓它成為動態和靜態,也為同時 weakly 和強型別。雖然出生為靜態型別語言,C# 會變成動態中鍵入使用動態關鍵字的這類的任何內容:

dynamic number = 10;
Console.WriteLine(number);

因為和動態是內容關鍵字不保留一個,這仍會保留如果您有現有的變數或名為動態的方法。

請注意 C# 4.0 doesn’t 強制您使用動態 C# 3.0 didn’t 強迫您使用 var、 lambdas 或物件初始設定式的方式相同。 C# 4.0 提供新的動態關鍵字,特別是以方便處理幾個已知的案例。 語言仍然基本上是以靜態方式具型別,即使它已加入能夠以更有效率的方式與動態物件互動。

您為什麼要使用動態物件? 第一次,您可能不知道您處理之物件的型別。 您可能線索,但不是以靜態方式鍵入給定的變數確實方式 — 這到底是什麼是發生在許多常見的情況下,例如當您使用的 COM 物件,或使用反映來抓取例項。 在此內容中動態關鍵字使某些情況下比較不痛苦應付。 撰寫動態程式碼會比較容易讀取和寫入、 ’s 容易的應用程式進行瞭解和維護。

第二個,您的物件可能原本就是變更的性質。 您可能會使用動態的程式設計環境,例如 IronPython 和 IronRuby 所建立的物件。 但是您也可以使用這項功能與 HTML DOM 物件 (限於 expando 屬性) 和特別建立能夠動態 natures 的 Microsoft.NET Framework 4 物件。

使用動態

它 ’s 一定要了解概念,在 C# 型別系統動態是一種型別。 它有非常特殊的意義,但絕對 ’s 型別而且 ’s 重要因此對待。 您可以指出動態做為一個變數您宣告的集合中的項目型別或方法的傳回值的型別。 您也可以使用動態做為方法參數的型別。 相反地,您 can’t 使用動態與 typeof 運算子,並 can’t 使用作為類別的基底型別。

下列程式碼將示範如何宣告動態變數的方法主體中:

public void Execute()  { 
  dynamic calc = GetCalculator();
  int result = calc.Sum(1, 1);
}

如果知道充分 GetCalculator 方法所傳回之物件的型別,您可以宣告該型別的變數 calc,或者您可以宣告為 var 變數,讓編譯器找出確切的細節。 但使用 var 或明確的靜態型別會要求您為特定的加總存在於 GetCalculator 傳回型別所公開的合約的方法。 如果該方法 doesn’t 存在,就會發生編譯器錯誤。

與動態,延遲關於正確性運算式在執行階段的任何決策。 程式碼會編譯,並解決在執行階段是只要加總的方法是儲存在變數 calc.類型上可用

您也可以使用關鍵字在類別上定義一個屬性。 在如此做時,您可以裝飾成員具有任何您喜歡例如公用、 受保護,及偶數靜態的可視性修飾詞。

圖 1 顯示動態關鍵字彈性。 主要的程式中有函式呼叫的傳回值以具現化的動態變數。 如果它 weren’t 事實接收函式,並傳回一個動態的物件,那就是沒有大問題。 它 ’s 有趣,看看有什麼變化時,例如您傳遞一個數字,然後試著在函式中連。

圖 1使用動態在一個函式簽名

class Program {
  static void Main(string[] args) {
    // The dynamic variable gets the return 
    // value of a function call and outputs it.
    dynamic x = DoubleIt(2);
    Console.WriteLine(x);

    // Stop and wait
    Console.WriteLine(“Press any key”);
    Console.ReadLine();
  }

  // The function receives and returns a dynamic object 
  private static dynamic DoubleIt(dynamic p) {
    // Attempt to "double" the argument whatever 
    // that happens to produce
    
    return p + p;
  }
}

如果您摘要值為 2,然後再試這個程式碼,您就會收到 4 的值。 如果在 2 摘要做為字串時,您而是取得 22。 在函式中將 + 運算子已解決動態地根據執行的階段型別運算元。 如果您將型別變更 System.Object 您發生編譯錯誤,因為 + 運算子 isn’t 在 System.Object 上定義。 動態關鍵字可讓 weren’t 可能沒有它的案例。

動態對。 System.Object

.NET Framework 4 直到有方法,傳回不同的型別,根據不同的條件來已可能只能由重新排序以通用的基底類別。 您可能藉由重新排序 System.Object 以解決這個問題。 可傳回 System.Object 函式可給呼叫者執行個體,可以轉型為幾乎任何項目。 因此方式使用動態比使用 System.Object 更好?

在 C# 4 在執行階段解析背後宣告動態變數實際的類型,然後編譯器只是假設在變數宣告只是動態物件支援任何作業。 這表示您真的可以撰寫如下圖所示,您預期要在執行階段會在該處的物件呼叫方法的程式碼:

dynamic p = GetSomeReturnValue();
p.DoSomething();

在 C# 4.0 編譯器 won’t 抱怨有關該程式碼。類似的程式碼使用 System.Object won’t 編譯,並需要自己某些 hacks — 反映或 adventurous 轉型 (Casting) — 才能運作。

var 對。動態

關鍵字 var 和動態是只顯然類似。變異數] 表示變數的型別有設定為 [編譯時期的初始設定式的型別。

但是,動態表示變數的型別是動態型別為可用的 C# 4.0 中。到最後動態和 var 有完全相反的意義。變異數是關於強化,以及改進靜態輸入。其目標是變數的確保推斷型別時,是變數的由編譯器查看精確型別初始設定式所傳回。

動態關鍵字是有關避免靜態鍵入完全。在變數宣告中使用時, 動態指示編譯器停止運作出變數的型別。該型別具有適合做為型別在執行階段發生問題時。var,與您的程式碼是為靜態型別如它本來有您選擇傳統的變數宣告中使用明確型別方法。

兩個關鍵字的另一個不同的是該 var 只可以出現在區域變數宣告內。您可以 can’t 使用 var 在類別上定義一個屬性也您可用它來指定傳回值或函式的參數。

身為開發人員您使用動態關鍵字與變數預期包含不確定型別的物件,例如物件傳回從 COM 或 DOM API,取得從動態語言 (例如 IronRuby,) ; 反映 ; 從動態內建的 C# 4.0 使用新的物件擴展能力。

動態型別雖然 doesn’t 略過型別檢查。它只會移動它們所有執行時間。如果型別不相容問題已在執行階段發現,然後會擲回例外狀況。

Dino Esposito* 即將產生 「 發展 ASP.NET MVC 」 從 Microsoft 按作者且 coauthor 的 「 Microsoft.NET:架構企業的應用程式 」 (Microsoft 按,2008年)。在義大利採用 Esposito 是在世界各地的產業活動頻繁演講者簡報。您可以在聯結他的部落格 weblogs.asp.net/despos.*

多虧給來檢閱這份文件的技術專家下列:  Eric Lippert