ViewBag dynamic 特性導致無法使用 LINQ 語法

寫 ASP.NET MVC CSHTML 時,我很習慣用 ViewBag 將變數從 Controller 傳到 View 端,只是簡單傳遞幾個字串、數值,為此大費周章宣告 Model 型別有點殺雞用牛刀。我們都知道 ViewBag 是一個 dynamic 型別,而 dynamic 型別的屬性、方法也會被視為 dynamic,編譯階段不檢查,執行階段見真章。

不過,最近學到一件事:一旦函式參數傳入 dynamic,其傳回值也會被視為 dynamic,而此時將無法使用 Lambda 運算式

來看下面這個例子。我計算透過 ViewBag.DateString 傳遞 "2017/08/26"格式字串 View,在 CSHTML 裡我用變數 dateStr 接入此字串,試著查 Length,跑 Split('/').First() 都沒問題。再來我寫了一個簡單函式 - MySplit,輸入 string,傳回 Split('/') 後的 string[]。將 dateStr 當參數傳入 MySpit,取傳回 string[] 的 Length OK,但想對 string[] 做 Any(o => o.Length > 3) 卻產生錯誤:

Error  CS1977  Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. 無法將 Lambda 運算式當做動態分派作業的引數,而未先將它轉型為委派或運算式樹狀架構型別

依照錯誤訊息指示,(string[])MySplit(dateStr) 將其強轉型後問題即告排除。至此我才發現,原來不只 dynamic 的屬性會被視為 dynamic,連一般的函式方法,只要傳入 dynamic 傳回結果也會被視為 dynamic。這應該跟參數有 dynamic 時 .NET 會改用複雜機制動態觸發函式有關,詳情可參考前文:方法多載(Method Overloading)與 dynamic

我們用 DateTime.ParseExact 測試,傳入 dateStr,在傳回的 DateTime 上寫 DarkthreadYear 都可以編輯成功(當然,執行階段必爆無夷),而由 Visual Studio 的顯示也可確認它被視為 dynamic。

而在這個案例中,更簡單的解法是將 var dateStr 改成 string dateStr,多打兩個字元,問題消失殆盡!

了解到這個特性,我決定養成一個習慣,不再用 var 宣告變數承接 ViewBag 傳遞過來的資料,而要明確宣告變數型別。如此在編輯階段可全程享受 Visual Studio 的強型別檢查與 Intellisense 支援,也避免衍生 Lambda 運算式碰壁的困擾,而依據先前研究,參數為 dynamic 時,.NET 將改用較複雜的動態機制處理函式呼叫,使用強型別也將有助於提高效能,一舉多得,何樂不為?

歡迎推文分享:
Published 26 August 2017 11:37 AM by Jeffrey
Filed under: ,
Views: 2,086



Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

Search

Go

<August 2017>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

This Blog


Syndication