1. 程式人生 > >C#4.0 新特性 動態型別Dynamic

C#4.0 新特性 動態型別Dynamic

        本文主要旨在與網友分享.Net4.0的Dynamic 對Duck Type 的支援。

    一、.net4.0主要新特性

        .Net4.0在.Net3.5基礎上新增的主要特性有:可選引數、命名引數和Dynamic。具體請閱生魚片的這篇博文。這裡我們著重講解C#4.0的Dynamic特性,對於其他特性大家可以在VS2010內嘗試一下。總之.Net在不斷進步中。

     二、ExpandoObject普通應用  

       ExpandoObject 類,“需引用System.Dynamic名稱空間” 。請看以下程式碼:       

複製程式碼 1dynamic Customer
=new ExpandoObject(); 2Customer.Name ="Lucy"; 3Customer.Age =20; 4Customer.Female =true; 5Console.WriteLine(Customer.Name + Customer.Age + Customer.Female); 6Console.ReadKey(); 複製程式碼

輸出<< Lucy20True,這裡已經類似javascript 的var obj ={}; obj.Name ='lucy'。但又不完全相同,因為不能在clr執行時動態生成屬性或者方法。但至少比.NET3.5先進了。

    三、Dynamic 動態型別對DuckType 的支援

      1.前不久在園子裡面看見了thinking的這篇博文,文中有這麼一段程式碼:

複製程式碼 staticclass Calculator { publicstatic T Add<T>(T t1, T t2) { dynamic d1 = t1; dynamic d2 = t2; return (T)(d1 + d2); } } publicstaticvoid Main(string[] args){ int i = Calculator.Add(1, 2); double d = Calculator.Add(
1.1, 2.2); string s = Calculator.Add("abc", "def"); Console.WriteLine(i +""+ d +""+ s); } 複製程式碼

輸出:

>>3 3.3 abcdef

作者在文中指出了以上C#程式碼是為了通過動態型別來實現基於duck typing的泛型引數約束

為了在C#支援Duck Type還有一個重要的.Net4.0特性有必要提及到,這也是本文重點討論的內容。

它就是:“DynamicObject” 該類位於System.Dynamic 名稱空間下。在VS2010內就可以看見該類的成員列表,截圖如下:

所屬方法都是虛方法,我們可以重寫這些虛方法。這裡主要看TryInvokeMember()方法。這個方法VS2010給出了詳細的描述。

根據VS2010註釋,由於我的VS2010是英文版的,這裡就不貼出英文註釋了。簡單介紹一下如何使用這個方法:假設我們一個類OurClass它繼承了DynamicObject 這個Class。OurClass中有一個方法OurMethod()。接著在OurClass 類中 重寫 TryInvokeMember這個基類虛方法。以上設定完後以後只要OurClass 的OurMethod方法一旦被呼叫都先執行一下重寫後的

  TryInvokeMember()方法。也許您會問這樣到底有何用途?OK!請先看javascript這段程式碼片段: 複製程式碼 1 function tryInvokeMember(obj) { 2 if (obj &&typeof obj.ourMethod ==="function") { 3 return obj.ourMethod(); 4 } 5 alert('未找到!'); 6 returnnull; 7 } 8 9 var ourObj1 = {}; 10 ourObj1.Method =function () { 11 alert('111'); 12 }; 13 14 var ourObj2 = {}; 15 ourObj2.ourMethod =function () { 16 alert('已經找到ourMethod並且執行'); 17 }; 18 19 tryInvokeMember(ourObj1); 20 tryInvokeMember(ourObj2); 複製程式碼 大家讀完這段js程式碼後應該會明白為什麼我要重點討論C#4.0中的DynamicObject了吧?真正的目的就是:在DuckType 類(鴨子) 方法(鴨子叫)執行之前,我們要判斷物件的類是否是具備鴨子叫的功能?如果不具備就不應該執行,否則程式勢必會丟擲異常。C#中如何實現呢?步驟如下:

      1、建立DynamicAnimal 類繼承DynamicObject類,並且重寫TryInvokeMember虛方法:

複製程式碼 publicclass DynamicAnimal : DynamicObject { publicoverridebool TryInvokeMember(InvokeMemberBinder binder, object[] args, outobject result) { bool success =base.TryInvokeMember(binder, args, out result); //如果方法不存在,請將result 這個out引數賦值為nullif (!success) result =null; //如果這個地方返回false 將會引發異常returntrue; } } 複製程式碼

     2、建立兩個DuckType類,分別為Duck 和 Human:

複製程式碼 1 publicclass Duck : DynamicAnimal 2 { 3 publicstring Quack() 4 { 5 return"鴨子嘛,就Quack吧!"; 6 } 7 } 8 publicclass Human : DynamicAnimal 9 { 10 publicstring Talk() 11 { 12 return"人類是用Talk,而不是Quack"; 13 } 14 } 複製程式碼

    3、在Console 內 建立DuckType的呼叫方法:

1 publicstaticstring DoQuack(dynamic animal) 2 { 3 string result = animal.Quack(); 4 return result ??"...人類當然不會鴨叫..."; 5 }    4、Console 內 Main方法呼叫: 複製程式碼 1 staticvoid Main(string[] args) 2 { 3 var duck =new Duck(); 4 var cow =new Human(); 5 Console.WriteLine("鴨子是Quack"); 6 Console.WriteLine(DoQuack(duck)); 7 Console.WriteLine("人類是talk"); 8 Console.WriteLine(DoQuack(cow)); 9 Console.ReadKey(); 10 } 複製程式碼 程式執行結果如下: