最近剛接觸WPF,雖然開發習慣還是像在使用 WinForm
比較近接WPF的用法都還沒使用到
所以想試試看MVVM當中的ViewModel
大致提到 (明確轉型 explicit )和LINQ的Cast限制
以及繼承類別後的轉型問題
還有多載運算子的問題
最近因工作需求開始接觸 WPF
加上本身也在慢慢研究MVC
總覺得未來一定會用到 ViewModel
因此開始在測試及研究 ViewModel該如何去設計
以下的想法是剛接觸這塊區域的新手想的
在OOP上應該本身就不該這樣設計(純粹因為方便而已)
紀錄一下,如未來有人有相同的問題可以參考一下
情境簡單敘述如下:
我在 原始資料 取出的東西是IEnumerable<DBData.Product>
這當中 Model 這是已經包裝好,我無法做修改的 DBData.Product Class
此時我需要對UI 做一些額外的紀錄資訊,如資料操作(新增,修改。顏色要不同)
理所當然想到 做一個 ViewModel 使用 繼承的方式 繼承 DBData.Product 做一個 UIProduct
如: public class UIProduct: DBData.Product
這時候 當未來需要將資料更新回DB 就可以直接使用UIProduct 向上轉型回 DBData.Product 即可
理論上 就可以直接使用 LINQ的 Cast<> 作轉換及可
IEnumerable<UIProduct> => IEnumerable<DBData.Product> 這方向可以,因為是向上轉型
但是
IEnumerable<DBData.Product> => IEnumerable<UIProduct> 這方向就不行 這就變成向下轉型
本以為只需要明確的定義即可達成 轉型
所以如果 當我可以變更 DBData.Product這Class 就可以添加 explicit 去做明確轉型(當初以為這樣做或許我就能向下轉了)
測試結果會是 explicit 無法對衍生類別使用,再寫程式的時候就會提示錯誤
當初因為不能變更DBData.Product這Class 所以在做 explicit 之前 突然想到是否可以使用擴充方法去實作 explicit
Google相關資訊之後發現,網路上已經有人詢問過,也有回答
https://stackoverflow.com/questions/8306614/extension-method-and-explicit-casting
簡單來說就是不行這樣做
擴充方法不可以 作 operator 的覆寫
最多是使用擴充方法 將 DBData.Product提供一個新的方法轉型成為UIProduct
以上問題後來使用其他方式去解決,因為本來以為做了 explicit 之後 就可以使用LINQ 的 Cast 作轉換
結果測試後發現小問題,我猜應該是使用上的限制,Google之後沒找到相關資料可以驗證是什麼原因
網路上有人回答說 LINQ Cast 內部的做法
https://stackoverflow.com/questions/4015930/when-to-use-cast-and-oftype-in-linq
foreach (object obj in source) yield return (TResult) obj;
本來以為因為使用 (TResult) 就會去呼叫覆寫後的 explicit
但是不知道是泛型的關係,單獨使用 覆寫後的 explicit 會成功
但是透過 LINQ Cast 卻無法正確對應(並不會去使用 explicit )
LINQ OfType一樣也會有這問題
這問題因為不清楚關鍵字該如何搜尋,所以還沒找到相關原因(未來有找到再補上)
最後解決方法 只能使用 LINQ Select(d => (MyUseType)d );
利用這方式將我要的類別轉型出來
結論
- 繼承相關類別再做轉型的operator覆寫上,會有限制(會跳出 "衍生類別之間不可進行使用者定義的轉換" 錯誤)
因為很少去做 explicit 所以一直沒注意到這限制(有興趣的可以順便看 implicit,implicit一樣無法對衍生類別作轉換) - 雖然本來有猜想到 擴充方法 無法對 operator 作覆寫或擴充。不過沒實際去測試過,經由測試後確定的確無法使用
- LINQ Cast和 OfType的限制,並不會呼叫 覆寫後的 explicit
- operator 的多載(覆寫) 可參考微軟的資料,本來以為Cast是使用 as 但查詢後 as 也無法多載。
所以就算真的Cast內部使用 as作轉換,對我目前的使用上意義也不大 - 另外 因為VM存在另一個List裡面,為了方便和預計新增的資料作比較所以有 override Equals。
VS會提醒說 GetHashCode也要override 原因如微軟所說,為了保證不會出問題強烈建議兩個都 override