上周碼程序的時候碰到個問題,因為設計上的約束,一個方法接受的參數只能為List<object>類型,然而該方法需要處理的真實數據則是確定的List<Currency>。然而C#不允許顯示的直接轉換類型,並且兩個方向上都不可以操作。這個問題讓我爆了一會兒,最后在MSDN上找到了一個OfType<T>的拓展方法可以完成這件事。
Enumerable.OfType<TResult> 方法:
此方法通過使用延遲執行實現。 即時返回值為一個對象,該對象存儲執行操作所需的所有信息。 只有通過直接調用對象的 GetEnumerator 方法或使用 Visual C# 中的 foreach(或 Visual Basic 中的 For Each)來枚舉該對象時,才執行此方法表示的查詢。
OfType<TResult>(IEnumerable) 方法僅返回 source 中那些可以轉換為 TResult 類型的元素。 如果元素不能轉換為 TResult 類型,但卻不想接收異常,則使用 Cast<TResult>(IEnumerable)。
此方法是少數標准查詢運算符方法之一,標准查詢運算符方法可應用於含有非參數化類型(如 ArrayList)的集合。 這是因為 OfType<TResult> 擴展了類型 IEnumerable。 OfType<TResult> 不僅無法應用於基於參數化的 IEnumerable<T> 類型的集合,也無法應用於基於非參數化的 IEnumerable 類型的集合。
通過將 OfType<TResult> 應用於實現 IEnumerable 的集合,可以獲得使用標准查詢運算符查詢集合的能力。 例如,將 Object 的類型參數指定為 OfType<TResult> 將返回一個對象,其類型為 C# 中的 IEnumerable<Object> 或 IEnumerable(Of Object) 中的 Visual Basic,標准查詢運算符可應用於該對象。
來看個直觀的例子:
static void Main(string[] args) { List<object> currencyList = new List<object>() { new Currency(){Id = Guid.NewGuid(), Name = "a"}, new Currency(){Id = Guid.NewGuid(), Name = "b"}, new Currency(){Id = Guid.NewGuid(), Name = "c"} }; List<object> currencyList1 = new List<object>() { "a", "b", "c" }; List<Currency> currencies = currencyList.OfType<Currency>().ToList(); List<Currency> currencies1 = currencyList1.OfType<Currency>().ToList(); Console.WriteLine("currencies list:"); foreach (var item in currencies) { Console.WriteLine(item.Id); } Console.WriteLine("currencies1 list:"); foreach (var item in currencies1) { Console.WriteLine(item.Id); } }
這段代碼中,currencies中是合法的Currency對象,所以可以被轉換。而currencies1中是string對象,不是Currency,所以不能被轉換,也不會拋異常。最后currencies1的結果是個空的List,而不是null。這段代碼的輸出結果如下: