C# 2.0 引入泛型、匿名方法、Predicate<T>,使集合內建算法(如 List<T>.FindAll)極其優雅。本文演示如何為自定義數據結構實現同樣風格的 FindAll,核心在於:實現 IEnumerable<T> + 接收 Predicate<T> 委托 + 內部 foreach 遍歷。
List books = Library.GetBooks();
List found = books.FindAll(delegate(Book b) {
return b.ISBN.StartsWith("978-7");
});
foreach (var b in found) Console.WriteLine(b.ISBN);
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
public class MyVec : IEnumerable
{
private readonly List _inner = new List();
// 1. 索引器 + 隱式轉換語法糖:vec += item
public static MyVec operator +(MyVec vec, T item)
{
vec._inner.Add(item);
return vec;
}
// 2. 核心算法:FindAll 接收 Predicate
public MyVec FindAll(Predicate match)
{
var result = new MyVec();
foreach (T item in _inner)
if (match(item))
result._inner.Add(item);
return result;
}
// 3. 實現 IEnumerable 支持 foreach
public IEnumerator GetEnumerator() => _inner.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
// 4. 友好輸出
public override string ToString()
{
var sb = new StringBuilder();
foreach (var item in _inner)
sb.Append(item).Append(',');
return sb.Length > 0 ? sb.Remove(sb.Length - 1, 1).ToString() : "";
}
}
class Program
{
static void Main()
{
var vec = new MyVec();
vec += 12;
vec += 15;
vec += 32;
Console.WriteLine("原向量: " + vec); // 12,15,32
// 匿名委托過濾 < 20
var small = vec.FindAll(delegate(int x) { return x < 20; });
Console.WriteLine("過濾後: " + small); // 12,15
// Lambda 寫法 (C# 3.0+)
var large = vec.FindAll(x => x >= 20);
Console.WriteLine("大於等於20: " + large); // 32
Console.ReadLine();
}
}
// 在 MyVec 中添加
public MyVec Where(Func predicate) => FindAll(predicate); // 別名
public MyVec Select(Func selector)
{
var result = new MyVec();
foreach (var item in _inner) result += selector(item);
return result;
}
public bool Any(Predicate predicate)
{
foreach (var item in _inner) if (predicate(item)) return true;
return false;
}
public T FirstOrDefault(Predicate predicate)
{
foreach (var item in _inner) if (predicate(item)) return item;
return default;
}
| 技術點 | 作用 |
|---|---|
Predicate<T> | 標準「條件判斷」委托签名:bool Predicate(T obj) |
| 匿名方法 / Lambda | 內聯定義邏輯,捕獲外部變量形成閉包 |
IEnumerable<T> | 統一遍歷協議,支持 foreach、LINQ 擴展方法 |
運算符重載 + | 提供 vec += item 語法糖,提升 DSL 感 |
| 迭代器模式 | 內部用 List<T> 存儲,對外暴露 IEnumerable<T>,封裝變動 |
entities.FindAll(e => e.IsAlive))rules.FindAll(r => r.Match(context)))「為自定義結構實現 FindAll(Predicate<T>)」只需三步:實現 IEnumerable<T>、內部 foreach 遍歷、接收 Predicate<T> 返回新集合。這正是 C# 2.0 泛型+委托帶來的表達力飛躍——算法與數據結構解耦,業務邏輯以委托形式注入。現代代碼請直接使用 List<T> + LINQ,但在框架開發、DSL 設計、高性能專用結構場景,此模式依然極具價值。