C# Enumerable 的 OfType 和 Cast 介紹

OfType 和 Cast 可以將集合中特定類型的內容取出,並將其轉換為 IEnumerable<T>
    
List<object> list = new()
{
    "A",
    "B",
    "C",
    100,
    200,
    300
};

IEnumerable<string> strings = list.OfType<string>();
Console.WriteLine(string.Join(", ", strings)); // A, B, C

IEnumerable<int> ints = list.OfType<int>();
Console.WriteLine(string.Join(", ", ints)); // 100, 200, 300
    

上面是示範 OfType ,那 Cast 呢?OfType 和 Cast 的差別就在於 OfType 遇到無法轉換的會忽略,而 Cast 遇到無法轉換的會拋出 System.InvalidCastException 例外
    
List<object> list = new()
{
    "A",
    "B",
    "C",
    100,
    200,
    300
};

IEnumerable<string> strings = list.Cast<string>();
Console.WriteLine(string.Join(", ", strings)); // 拋出 System.InvalidCastException 例外
    

錯誤訊息如下:
    Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.
   at System.Linq.Enumerable.CastIterator[TResult](IEnumerable source)+MoveNext()
   at System.String.Join(String separator, IEnumerable`1 values)
   at Program.<Main>$(String[] args) in C:\Users\ruyut\Documents\RiderProjects\test\2022\ConsoleAppDotNet6Test\ConsoleAppDotNet6Test\Program.cs:line 12

Process finished with exit code -532,462,766.
    

為什麼是 12 行拋出例外呢?因為 IEnumerable 是 yield return,簡單來說就是不會立即執行,用到才做,且足夠就停止。所以到第 12 行真的要使用的時候發現有無法轉換的資料時就拋出例外了。

用途

OfType 的主要用途和上面示範的一樣,就是將集合中指定類型的物件取出,例如 ArrayList(已不建議使用)、List<dynamic> 或 List<object> 等等。

兩者都可以將 ArrayList 和陣列(array) 等集合轉換為 IEnumerable 以便使用 LINQ

而 Cast 則是用於轉換已經確定的集合,例如將 string[] 轉換為 IEnumerable<string> 。因為已經確定是 string,不會出現其他類型的內容,如果拋出例外,那就代表真的是出現「例外情況」了。

參考資料:
Microsoft.Learn - Enumerable.OfType<TResult>(IEnumerable) Method
Microsoft.Learn - Enumerable.Cast<TResult>(IEnumerable) Method

留言