在 C# 中,要使用 foreach 循環遍歷一個對象,該對象必須滿足以下條件之一:
1. 實現 IEnumerable 或 IEnumerable 接口
- 非泛型版本:System.Collections.IEnumerable
public class MyCollection : IEnumerable
{private int[] _data = { 1, 2, 3 };public IEnumerator GetEnumerator(){return _data.GetEnumerator();}
}
- 泛型版本:System.Collections.Generic.IEnumerable(推薦)
public class MyCollection<T> : IEnumerable<T>
{private List<T> _data = new List<T>();public IEnumerator<T> GetEnumerator(){return _data.GetEnumerator();}IEnumerator IEnumerable.GetEnumerator() // 顯式實現非泛型接口{return GetEnumerator();}
}
2. 提供 GetEnumerator() 方法的公共非泛型實現
- 如果類沒有顯式實現 IEnumerable,但提供了返回 IEnumerator 的公共方法,foreach 仍可工作:
public class MyCollection
{private int[] _data = { 1, 2, 3 };public IEnumerator GetEnumerator(){return _data.GetEnumerator();}
}
3. 使用 yield return 自動生成枚舉器
- 編譯器會自動為包含 yield return 的方法生成 IEnumerable 實現:
public class MyCollection
{public IEnumerable<int> GetItems(){yield return 1;yield return 2;}
}// 使用時:
foreach (var item in new MyCollection().GetItems()) { ... }
4. 數組或字符串(語言內置支持)
- 數組和字符串即使未顯式實現接口,也能直接用 foreach 遍歷(編譯器特殊處理):
int[] array = { 1, 2, 3 };
foreach (int num in array) { ... } // 合法string str = "hello";
foreach (char c in str) { ... } // 合法
關鍵點總結
- 必須:對象需提供 GetEnumerator() 方法(通過接口或顯式實現)。
- 推薦:優先使用泛型接口 IEnumerable 以獲得類型安全和性能優勢。
- 例外:數組和字符串是語言內置的特殊類型。
示例:完整泛型實現
using System.Collections.Generic;public class MyList<T> : IEnumerable<T>
{private List<T> _items = new List<T>();public void Add(T item) => _items.Add(item);public IEnumerator<T> GetEnumerator() => _items.GetEnumerator();System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()=> GetEnumerator();
}// 使用:
var list = new MyList<int>();
list.Add(1);
list.Add(2);
foreach (var item in list) { ... } // 正常遍歷
通過滿足上述條件,任何自定義對象都可以使用 foreach 遍歷。