[轉]理解C# 4 dynamic(1) - var, object, dynamic的區別以及dynamic的使用

 

閱讀目錄:html

一. 爲何是它們三個函數

二. 可以任意賦值的緣由post

三. dynamic的用法this

四. 使用dynamic的注意事項spa

一. 爲何是它們三個?

拿這三者比較的緣由是它們在使用的時候很是類似。你能夠用它們聲明的變量賦任何類型的值。.net

看看下面的示例:code

var a = 1; object b = 1; dynamic c = 1;

 你還可使用關鍵字爲它們賦上更加複雜的類型htm

var a = new string[]{"1"}; object b = new string[]{"1"}; dynamic c = new string[]{"1"};

二. 可以任意賦值的緣由

 上面的例子中,看起來三者很是類似,可是背後的原理倒是很是不一樣。對象

var是C# 3中引入的,其實它僅僅只是一個語法糖. var自己並非一種類型, 其它二者object和dynamic是類型。blog

var聲明的變量在賦值的那一刻,就已經決定了它是什麼類型。

因此若是你這樣使用,就會有編譯錯誤:

var a = 1; a = "Test";

 

object之因此可以被賦值爲任意類型的緣由,其實都知道,由於全部的類型都派生自object. 因此它能夠賦值爲任何類型:

object a = 1; a = "Test";

 

那麼dynamic呢?

它是C#引入的新類型,它的特色是申明爲dynamic類型的變量,不是在編譯時候肯定實際類型的, 而是在運行時。

因此下面的代碼是可以經過編譯的,可是會在運行時報錯:

dynamic a = "test"; a++;

上面代碼內部處理的過程是怎樣的呢?

首先, dynamic類型賦值爲字符串"test", 運行++操做的時候,.net會去尋找當前的賦值類型string中是否支持++操做,發現不支持,出現異常。

因此,若是這樣修改一下,就可讓代碼正常運行起來

dynamic a = "test"; a = 1; a++;

三. dynamic的用法

1 直接使用該類型,能夠很是方便的插入屬性, 方法

複製代碼
static void Main(string[] args) { dynamic person = new System.Dynamic.ExpandoObject(); person.Name = "cary"; person.Age = 25; person.ShowDescription = new Func<string>(() => person.Name + person.Age); Console.WriteLine(person.Name + person.Age + person.ShowDescription()); Console.ReadLine(); }
複製代碼

枚舉全部成員

foreach (var property in (IDictionary<String, Object>)dynEO) { Console.WriteLine(property.Key + ": " + property.Value); }

3 簡化反射

經常使用的處理反射的例子:

object calc = GetCalculator(); Type calcType = calc.GetType(); object res = calcType.InvokeMember( "Add", BindingFlags.InvokeMethod, null, new object[] { 10, 20 }); int sum = Convert.ToInt32(res);

使用dynamic以後:

 dynamic calc = GetCalculator();
 int sum = calc.Add(10, 20);

 

四,使用dynamic的注意事項

有了dynamic,.net就以及有了動態類型的優點,可是因爲對於dynamic類型的全部操做,都是在運行時肯定的,全部錯誤沒法在編譯時候出現,使用的時候,就須要很是當心。

由於dynamic是類型,因此若是函數接受的是肯定類型的參數,是不能傳入dynamic類型的,這樣會有編譯錯誤。好比:

複製代碼
public int Add(int a, int b){ return a + b; } dynamic test1 = 1; dynamic test2 = 2; Add(test1, test2);
複製代碼

下面是對上面的例子的修正,謝謝Alan@Net. 你們能夠實驗一下

    1. #15樓 Alan@Net   2014-02-04 21:30
      爲何我copy你最後一個例子,並無報錯?
    2. #16樓[樓主] JustRun   2014-02-07 08:30
      @Alan@Net 應該是編譯不經過,我待會試試
    3. #17樓[樓主] JustRun   2014-02-08 08:29
      @Alan@Net 是不會報錯,對於普通的類型,int這樣的,不會有問題。 可是若是是對象類型,運行時會報錯。

 

另外,在咱們本身在寫函數時,最好不要將dynamic類型做爲函數的參數,這就像是使用object做爲函數參數同樣,會爲程序的維護帶來後續的麻煩。

沒有人可以肯定使用者傳入的是什麼,並且編譯時候不會有問題。若是錯誤出如今運行時,就有多是災難。

 

ExpandoObject使用場合

在傳遞對象,可是又不想建立一個class或者struct的時候,ExpandoObject就是一個很是好的選擇。 假如咱們有一個SendMail的函數,功能是發送一個通知郵件給客戶,郵件的文本模板,以下: Dear [Name], We have sent the gift to your address: [Address]

在具體發送郵件的時候, [Name]和[Address]的內容是從函數GetMailParameters()動態讀取出來的。 那麼函數GetMailParameters的返回值如何定義好呢?

若是爲GetMailParameters()函數建立一個struct或者class來傳遞, 有些小題大作了,並且定義的struct和class重用性會很是低。

若是使用了ExpandoObject, 就很是容易的解決了這個問題。

複製代碼
public dynamic GetMailParameters() { dynamic mailParameters = new ExpandoObject(); mailParameters.Name=」Peter」; mailParameters.Address=」Shanghai China」 return mailParameters; }
複製代碼

就算之後郵件模板改變,添加了新的變量,也只是簡單的在ExpandoObject上擴展一個屬性就能夠了。

 

轉自:http://www.cnblogs.com/JustRun1983/p/3163350.html

相關文章
相關標籤/搜索