熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#的強類型解釋

2013-11-13 09:43:14  來源: .NET編程 

  一直說C#是強類型語言通俗地講便是指C#中的變量在開發時的類型便是明確的String便是StringInt就是Int毫無爭議強類型的好處有很多張嘴便可隨意舉上幾例

  能夠享受代碼提示功能

  能夠獲得重構工具的支持

  能夠在編譯期發現更多錯誤

  ……

  不過C#也不是絕對的強類型語言因為它也有弱類型那就是Object我們知道Object是所有類型的最終基類任何類型的對象都可以使用Object來引用可是一旦轉化成Object的變量之後代碼提示便消失了即使我們明確對象的確切類型也必須通過Cast才能使用——更何況它形成了一種被濫用誤用的機會例如一段錯誤代碼可能會傳入一個不符合約定類型的對象那麼就會造成錯誤更嚴重的是這樣的錯誤可能只要在運行時才能被發現編譯器對此無能為力

  類似的實踐其實很多例如方法盡可能接受抽象的類型而返回具體的類型

  ASPNET MVC中對於強類型一說最典型的方面便是視圖在ASPNET MVC中每種視圖(ViewPartialLayout)都可以選擇弱類型和強類型兩種基類兩者的區別便是Model的類型強類型視圖的唯一區別便是其Model屬性為范型參數所指定的類型——而弱類型則自然就是Object了在這裡我提出一個最佳實踐總是使用強類型的視圖並且所有數據都從Model中獲取這麼做可能會在一定程度上增加了代碼量因為我們需要為每個視圖建立一個Model不過我認為這是值得的在強類型的視圖中VS中能夠對Model的各種成員做出豐富的代碼提示我們便可以快速地輸入代碼並確保不會出現拼寫之類的低級錯誤如果使用了ViewData這個弱類型的字典那麼每次我們獲取某個值之後都必須將其Cast成具體的類型才能使用這無疑使視圖模板變得復雜而難以維護

  其實以上的准則還有另一個層面的內容使用項目模板安裝了ASPNET MVC之後在~/Views/Shared/LogOnUserControlascx文件中可以發現對PageUser屬性的直接訪問這自然可以運行但是其帶來的後果是弱化了aspx/ascx/master文件的模板概念而重新讓其意識到我是一張頁面在ASPNET MVC框架中我們要時刻記著項目中沒有頁面我們始終使用Controller中的Action方法來處理請求而每個請求需要對應一個磁盤上物理文件的思維方式一定需要改變(無論是在用WebForms模型還是MVC模型)直接訪問PageUser屬性也使我們很難為視圖進行獨立的單元測試因為視圖與HttpContext直接耦合而HttpContext的Mock相當困難

  在《最佳實踐》的示例中我為每個視圖都構建了一個Model它們都在MyMvcDemoWebUIModels項目中值得一提的是由於業務的需要視圖之間很可能出現數據共享例如View和Layout(更ASPNET的說法是Page與Master Page)之間共享同一個Model更進一步兩者之間其實是多對多的關系如果我們為每個ViewPage定義了強類型的Model又如何應對同一個ViewPage套用不同ViewMasterPage的情況呢?這個問題最自然的解決方式便是使用接口一個Model對象不可以有多個父類但是完全可以實現多個接口因此我們往往為強類型的ViewMasterPage指定一個接口作為其泛型參數從示例中您也可以發現SiteMaster的類型為ViewMasterPage<ISiteMasterModel>而每個ViewPage的Model類型都實現了ISiteMasterModel接口

  使用ViewData的另一個壞處是必須使用字符串作為鍵進行訪問字符串是什麼?是常量分散在各處的常量是維護性的大敵而使用ViewData則幾乎無可避免地將字符串常量分散在控制器和視圖兩個地方——您可能會覺得使用枚舉不就解決這個問題了嗎?如果這麼做相當於為每個視圖定義不同的枚舉類型那麼我們為什麼不直接構造強類型的Model呢?使用字符串作為鍵的另一個壞處是無法在編譯期發現問題如果您一不小心拼寫錯誤了怎麼辦呢?您可能會覺得原本aspx就必須到運行時才會動態編譯不過現在ASPNET MVC的模板已經增加了相關的MSBuild Task或者使用ASPNET的預編譯功能都可以在編譯時對視圖進行檢查了這也是我建議大家使用aspx而不是另一種DSL來構建視圖的原因——aspx的周邊支持實在是太豐富了

  不過在視圖中字符串常量並非只出現在ViewData的訪問上例如使用ASPNET MVC框架模板創建項目之後SiteMaster中生成導航欄鏈接的代碼是這樣的

  <ul id=menu>

  <li><%= HtmlActionLink(Home Index Home)%></li>

  <li><%= HtmlActionLink(About About Home)%></li></ul>

  代碼使用了HtmlActionLink這個輔助方法生成一個導向至某個Action的鏈接只可惜這裡又出現了字符串參數表示的Controller名和Action名事實上如果您下載了ASPNET MVC RC的源代碼之後能夠發現其中的MvcFutures項目中包含了強類型的ActionLink輔助方法於是我們的代碼就能修改為如下模樣(參見《最佳實踐》的示例)

  <li><%= HtmlActionLink<HomeController>(c => cIndex() Home) %></li>

  <li><%= HtmlActionLink<HomeController>(c => cAbout() About) %></li><li><%= HtmlActionLink<AccountController>(c => cRegister() Register) %></li><li><%= HtmlActionLink<AccountController>(c => cList() Admin) %></li>

  這下我們便可以使用Lambda Expression這個強類型的表示方法來告訴ActionLink方法究竟該生成導向至哪個Action方法的鏈接甚至我們可以在調用Action方法的同時指定其參數——例如最後一行代碼指定將查看第一頁內容而這些數據在交給URL Routing的配置後便能得到我們想要的URLMvcFutures中還定義了其他類似的輔助方法例如UrlHelper中的輔助方法則會直接生成一個URL鏈接——而不是一個元素可惜目前MvcFutures中的這些輔助方法編寫的並不完全正確因為它直接把方法名作為Action的名稱來使用而ASPNET MVC從某個預覽版開始引入了ActionNameAttribute可以為一個Action方法指定一個不同的Action名稱因此如果您使用ActionNameAttribute來改變Action名則很可能您需要構建自己的輔助方法不過這條准則依舊成立使用強類型的表示法生成URL地址

  如果您要使用MvcFutures中的內容則必須自行編譯MvcFutures項目有一點值得注意如果您使用直接編譯ASPNET MVC RC解決方案所得到的MicrosoftWebMvcdll就會發現它依賴的是SystemWebMvc Version= Culture=neutral PublicKeyToken=null而您開發時所使用的也就是安裝在系統中的程序集是SystemWebMvc Version= Culture=neutral PublicKeyToken=BFADE兩者不同自然難以兼容幸運的是您只要手動修改一下MvcFutures項目的程序集引用就可以了對您來說這一定不是問題

  看到這裡不知道您是否發現了一個比較嚴重的問題其嚴重程度大大降低了這些負責生成URL的輔助方法的可用性這是個什麼問題呢?又該如何解決呢?我在這裡先賣個關子下個星期我將公布這個問題以及它的解決方法——這部分內容並沒有包含在上次《最佳實踐》的講座中算是一個保留節目


From:http://tw.wingwit.com/Article/program/net/201311/11411.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.