var, dynamic 差別以及如何實作像 ViewBag 一樣的物件【转】
原文:http://kelp.phate.org/2011/11/var-dynamic-viewbag.html
var
在以前寫程式時要宣告以及 Instance 的時候一般會寫成這樣。
但從 C# 3.0 開始多了「var」,所以我們可以寫成這樣:
使用 var 的好處在於只需要打一次型別名稱。
var 宣告後的變數型別是固定的,未來程式在運作時無法改變型別(跟 JavaScript 不一樣),在程式撰寫時變數具有該型別的 IntelliSense。
說簡單一點就是「編譯器在編譯時會自動將 var 取代為適當的型別」。
dynamic
C# 4.0 多了「dynamic」,dynamic 跟 var 是截然不同的東西。
dynamic 允許在執行的過程替換變數的型別。
dynamic 還有一個特性就是編譯過程不會檢查值是否給對、呼叫的 method 是否存在、property 是否存在...等,而且 dynamic 沒有 IntelliSense。
筆者不太喜歡沒有 IntelliSense 的東西,因為很容易打錯字,所以沒必要的時候少用為妙。
有一點要注意的是:dynamic 變數存取不存在的 member、method 是為發生 Exception 的。
ExpandoObject
在 MVC 3 的時候 Controller 可以透過 ViewBag 將資料傳給 View。
底下的程式就是透過 ViewBag 設定網頁的標題:
ViewBag 就是一個 dynamic 的應用,而有些人可能會感覺很奇怪,就算是 dynamic 也不能存取不存在的 property,為什麼我可以丟任何的資料到 ViewBag 底下的任何一個 property 中。
其實 Instance ViewBag 的型別是 ExpandoObject,這個型別可以動態產生 property,所以才會有 ViewBag 這樣神奇的物件。
在以前寫程式時要宣告以及 Instance 的時候一般會寫成這樣。
1 | TestModel model = new TestModel(); |
1 | var model = new TestModel(); |
var 宣告後的變數型別是固定的,未來程式在運作時無法改變型別(跟 JavaScript 不一樣),在程式撰寫時變數具有該型別的 IntelliSense。
說簡單一點就是「編譯器在編譯時會自動將 var 取代為適當的型別」。
dynamic
C# 4.0 多了「dynamic」,dynamic 跟 var 是截然不同的東西。
dynamic 允許在執行的過程替換變數的型別。
1 2 3 4 | dynamic model = new TestModel(); model = new Exception(); model = 1; //這樣的寫法不會造成 Exception |
筆者不太喜歡沒有 IntelliSense 的東西,因為很容易打錯字,所以沒必要的時候少用為妙。
有一點要注意的是:dynamic 變數存取不存在的 member、method 是為發生 Exception 的。
1 2 | dynamic model = new Exception(); model.Title = "hello" ; //執行的時候此行程式會出錯 |
ExpandoObject
在 MVC 3 的時候 Controller 可以透過 ViewBag 將資料傳給 View。
底下的程式就是透過 ViewBag 設定網頁的標題:
1 2 3 4 5 | public ActionResult Index() { ViewBag.Title = "Index" ; return View(); } |
1 2 3 | < head > < title >@ViewBag.Title</ title > </ head > |
ViewBag 就是一個 dynamic 的應用,而有些人可能會感覺很奇怪,就算是 dynamic 也不能存取不存在的 property,為什麼我可以丟任何的資料到 ViewBag 底下的任何一個 property 中。
其實 Instance ViewBag 的型別是 ExpandoObject,這個型別可以動態產生 property,所以才會有 ViewBag 這樣神奇的物件。
1 | using System.Dynamic; |
1 2 3 | dynamic model = new ExpandoObject(); model.Title = "Index" ; model.Time = DateTime .UtcNow; |
另,试了一下在WCF中能不能用ExpandoObject来实现DTO的功能,结果被转化成了
System.Collections.Generic.Dictionary<string, object>,看来通过这种方式来避免使用DTO还是有一点问题。
不过这篇文章:Returning Dynamic Types from an Ajax Web Service Using C# 4.0 可以看到避免使用DTO的种可行性,但似乎是要在特定的WebService上以及使用Ajax来处理相应的响应(不可以是C#的代理类来处理匿名类型,否则会因为返回值是匿名类型会报异常)
一点说明:为什么在标题中要嵌入英文?原因是为了能够让国外的网友能查询到这篇文章。平常在Google上查资料的时候,经常参考国外网友的博客,帮助我解决了很多问题,所以我也想让他们能够参考我写的内容。当然文中我不可能全部译为英文,所以我尽量把代码粘全,靠代码说话吧。