C# 2.0 引入泛型、匿名方法與 Predicate<T> 委派,使 List<T>.FindAll 等內建演算法寫法極為優雅。本文探討如何為自訂資料結構實作相同風格的 FindAll,達到「忽略儲存細節、以委派表達演算法」的目標。
List<Book> thelib = Library.GetBooks();
List<Book> found = thelib.FindAll(delegate(Book b) {
return b.ISBN.StartsWith("978");
});
foreach (Book b in found) Console.WriteLine(b.ISBN);
FindAll 接受 Predicate<T> 委派(public delegate bool Predicate<T>(T obj);),內部以 foreach 走訪集合,符合條件者加入新集合回傳。此模式實為「演算法結構」與「判斷邏輯」分離的 Closure 應用。
public class MyVec<T>
{
private List<T> _list = new List<T>();
// 運算子多載:支援 vec += item 語法
public static MyVec<T> operator +(MyVec<T> a, T b)
{
a._list.Add(b);
return a;
}
// 核心:模擬 FindAll
public MyVec<T> FindAll(Predicate<T> match)
{
MyVec<T> result = new MyVec<T>();
foreach (T item in _list)
if (match(item)) result._list.Add(item);
return result;
}
public override string ToString()
{
return string.Join(",", _list.ConvertAll(x => x.ToString()).ToArray());
}
}
static void Main()
{
MyVec<int> vec = new MyVec<int>();
vec += 12; vec += 15; vec += 32;
MyVec<int> found = vec.FindAll(delegate(int x) { return x < 20; });
Console.WriteLine("original: " + vec); // 12,15,32
Console.WriteLine("found: " + found); // 12,15
Console.ReadLine();
}
若內部儲存非 List<T>,只需實作 IEnumerable<T>,即可在 FindAll 中以 foreach 統一走訪,達到對任何資料結構提供強大演算法支援。
透過泛型委派與 IEnumerable<T>,C# 2.0 讓開發者能以極簡潔語法,為自訂類別注入標準演算法行為,大幅提升程式碼可讀性與重用性。