Enumerable.Cast<T> 的核心作用是將非泛型的 IEnumerable 轉換為泛型版本 IEnumerable<T>。轉換後,我們即可盡情使用 LINQ 強大的標準查詢運算子(如 Where、Select、OrderBy 等),極大地提升了編碼效率與代碼可讀性。
MSDN 文檔中僅以 ArrayList 為例進行演示,許多開發者因此誤以為在 List<T> 普及的今天,Cast<T> 只有在維護 .NET 1.x 遺留代碼時才會用到。事實上,Cast<T> 的應用場景遠不止於此,它在處理各種非泛型集合、Windows Forms / ASP.NET 控件集合時極具價值。
先回顧一下 MSDN 的經典範例,理解其基本語法:
System.Collections.ArrayList fruits = new System.Collections.ArrayList();
fruits.Add("apple");
fruits.Add("mango");
IEnumerable<string> query = fruits.Cast<string>();
foreach (string fruit in query) Console.WriteLine(fruit);
同樣地,.NET 1.x 時代的其他非泛型集合(如 Array、非泛型 List 等)均適用此模式。
在 WinForms 開發中,ListView、ComboBox、DataGridView、TreeView 等控件的集合屬性(如 Items、Nodes)通常實現的是非泛型 IEnumerable 或 IList 接口。這使得 Cast<T> 成為操作這些控件數據的利器。
以 ListView 為例,其 Items 屬性類型為 ListView.ListViewItemCollection,該類實現了 IEnumerable:
public class ListView : Control
{
public ListView.ListViewItemCollection Items { get; }
public class ListViewItemCollection : IList, ICollection, IEnumerable { }
}
假設 ListView 綁定了一組 Employee 對象,我們可以輕鬆使用 LINQ 進行查詢:
// 獲取員工總數
int count = listView.Items.Cast<Employee>().Count();
// 判斷是否存在名為 "Bob" 的員工
bool exists = listView.Items.Cast<Employee>().Any(e => e.FirstName == "Bob");
提示: 若已持有綁定數據源的直接引用(如
List<Employee>),優先使用數據源查詢,性能更優;此處演示僅為展示Cast<T>用法。
Cast<T> 同樣適用於 ComboBox、DataGridView、TreeView 等控件:
// ComboBox 示例
var items = comboBox.Items.Cast<People>();
// DataGridView 行集合示例 (需轉換為 DataGridViewRow)
var rows = dataGridView.Rows.Cast<DataGridViewRow>()
.Where(r => !r.IsNewRow)
.Select(r => r.DataBoundItem as MyEntity);
// TreeView 節點示例
var nodes = treeView.Nodes.Cast<TreeNode>()
.Where(n => n.Checked);
Enumerable.Cast<T> 不僅是遺留代碼的「適配器」,更是連接非泛型集合世界與現代 LINQ 生態的橋梁。掌握它,能讓你在處理 UI 控件集合、COM 互操作對象、舊版 API 返回值時,同樣享受強類型與 LINQ 查詢帶來的開發體驗。