C#編程總結(十四)dynamic
介紹
Visual C# 2010 引入了一個新類型 dynamic。 該類型是一種靜態類型,但類型為 dynamic 的對象會跳過靜態類型檢查。 大多數情況下,該對象就像具有類型 object 一樣。 在編譯時,將假定類型化為 dynamic 的元素支持任何操作。 因此,您不必考慮對象是從 COM API、從動態語言(例如 IronPython)、從 HTML 文檔對象模型 (DOM)、從反射還是從程序中的其他位置獲取自己的值。 但是,如果代碼無效,則在運行時會捕獲到錯誤。
var與dynamic對比
1、var編譯時替換為實際類型,而dynamic實際是object類型。
一旦被編譯,編譯期會自動匹配var 變量的實際類型,並用實際類型來替換該變量的申明,這看上去就好像我們在編碼的時候是用實際類型進行申明的。而dynamic被編譯后,實際是一個object類型,只不過編譯器會對dynamic類型進行特殊處理,讓它在編譯期間不進行任何的類型檢查,而是將類型檢查放到了運行期。
2、智能感知。
以var聲明的變量,支持“智能感知”,因為visual studion能推斷出var類型的實際類型,而以dynamic聲明的變量卻不支持“智能感知”,因為編譯器對其運行期的類型一無所知。對dynamic變量使用“智能感知”,會提示“此操作將在運行時解析”。
簡單案例
編寫一個hello world的測試程序,定義DynamicTest類型,並增加Welcome方法,其參數為name.
然后創建dynamic對象,調用Welcome方法。參數為空。
using System; namespace DynamicSample { class Program { static void Main(string[] args) { dynamic obj = new DynamicTest(); obj.Welcome(); } } class DynamicTest { public void Welcome(string name) { Console.WriteLine("Hello {0},welcome to dynamic world.",name); } } }
看看發生什么事情呢,通過測試發現:
編譯通過,沒有任何異常。
運行時拋出異常,異常信息:
未處理Microsoft.CSharp.RuntimeBinder.RuntimeBinderException HResult=-2146233088 Message=“Welcome”方法沒有采用“0”個參數的重載 Source=Anonymously Hosted DynamicMethods Assembly StackTrace: 在 CallSite.Target(Closure , CallSite , Object ) 在 System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0) 在 DynamicSample.Program.Main(String[] args) 位置 E:\Donet\C#\DynamicSample\DynamicSample\Program.cs:行號 13 在 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在 System.Threading.ThreadHelper.ThreadStart() InnerException:
修正后:
class Program { static void Main(string[] args) { dynamic obj = new DynamicTest(); string name = "Tom"; obj.Welcome(name); Console.WriteLine("Input any key to exit."); Console.ReadKey(); } }
運行結果:
如果改為var,定義該對象,並調用方法,代碼如下,編譯器會報錯:
var v1 = new DynamicTest(); v1.Welcome();
錯誤信息:
錯誤 CS7036 未提供與“DynamicTest.Welcome(string)”的必需形參“name”對應的實參 DynamicSample Program.cs 15 錯誤 CS7036 There is no argument given that corresponds to the required formal parameter 'name' of 'DynamicTest.Welcome(string)' DynamicSample
dynamic應用范圍
1、在聲明中,作為屬性、字段、索引器、參數、返回值或類型約束的類型,都可以使用dynamic。
2、在顯式類型轉換中,作為轉換的目標類型。任何對象都可以隱式轉為dynamic。
3、在以類型充當值(如 is 運算符或 as 運算符右側)或者作為 typeof 的參數成為構造類型的一部分的任何上下文中。
通過一個實例來具體說明:
class DynamicUser { /// <summary> /// 字段 /// </summary> public dynamic userid; /// <summary> /// 屬性 /// </summary> public dynamic UserName { get; set; } /// <summary> /// 玩游戲 /// (dynamic可以作為參數、返回值等) /// </summary> /// <param name="game"></param> /// <returns></returns> public dynamic Play(dynamic game) { dynamic defaultGame = "Play Basketball."; dynamic secGame = "Play with mud."; if (game is int) { return defaultGame; } else { return secGame; } } /// <summary> /// 顯式類型轉換 /// </summary> public void ConvertToDynamic(object obj) { dynamic d; d = (dynamic)obj; Console.WriteLine(d); } /// <summary> /// 類型判定 /// (dynamic 可以使用is、as、typeof) /// </summary> public void TypeCheck() { int age = 20; Console.WriteLine("Age is Dynamic? {0}",age is dynamic); dynamic d = age as dynamic; Console.WriteLine("Age:{0}",d); Console.WriteLine("List<dynamic>'s type is {0}",typeof(List<dynamic>)); } }
測試用例:
DynamicUser user = new DynamicUser(); user.userid = 123; user.UserName = "Lucy"; user.ConvertToDynamic(user.userid); user.ConvertToDynamic(user.UserName); user.TypeCheck(); Console.WriteLine("Input any key to exit."); Console.ReadKey();
測試結果:
dynamic的執行效率
關於dynamic的效率問題,這里暫不展開,后續專門來討論...
應用
1、自動反射
2、COM組件互操作
3、混合編程,例如IronRuby和IronPython
4、處理Html DOM對象
5、還有一種應用,數據傳輸中格式轉換,如:對象轉json等,很方便