自定义一个可以使用foreach语句进行迭代的类(IEnumerable)
在c#中,凡是实现了IEnumerable接口的数据类型都可以用foreach语句进行迭代访问。所以,我们要定义一个可以使用foreach进行迭代访问的类,就必须要实现IEnumerable接口。
1 // 摘要: 2 // 公开枚举器,该枚举器支持在非泛型集合上进行简单迭代。 3 public interface IEnumerable 4 { 5 // 摘要: 6 // 返回一个循环访问集合的枚举器。 7 // 8 // 返回结果: 9 // 可用于循环访问集合的 System.Collections.IEnumerator 对象。 10 [DispId(-4)] 11 IEnumerator GetEnumerator(); 12 }
在IEnumerable中,只有一个GetEnumerator方法,而GetEnumerator返回一个IEnumerator对象,所以要看下IEnumerator的定义。
1 // 摘要: 2 // 支持对非泛型集合的简单迭代。 3 public interface IEnumerator 4 { 5 // 摘要: 6 // 获取集合中的当前元素。 7 // 8 // 返回结果: 9 // 集合中的当前元素。 10 // 11 // 异常: 12 // System.InvalidOperationException: 13 // 枚举器定位在该集合的第一个元素之前或最后一个元素之后。- 或 -在创建了枚举器后集合被修改了。 14 object Current { get; } 15 16 // 摘要: 17 // 将枚举器推进到集合的下一个元素。 18 // 19 // 返回结果: 20 // 如果枚举器成功地推进到下一个元素,则为 true;如果枚举器越过集合的结尾,则为 false。 21 // 22 // 异常: 23 // System.InvalidOperationException: 24 // 在创建了枚举器后集合被修改了。 25 bool MoveNext(); 26 // 27 // 摘要: 28 // 将枚举器设置为其初始位置,该位置位于集合中第一个元素之前。 29 // 30 // 异常: 31 // System.InvalidOperationException: 32 // 在创建了枚举器后集合被修改了。 33 void Reset(); 34 }
IEnumerator中有Current属性和MoveNet、Reset两个方法,所以要定义一个类来继承IEnumerator并实现这些方法属性。
通过IEnumerable和IEnumerator定义可以看出要实现foreach迭代,我们要定义两个对象,一个实现接口IEnumerable,一个实现接口IEnumerator,IEnumerable中的GetEnumerator()看作IEnumerator object的factory method 也未尝不可。
1 class CatArray : IEnumerable { 2 private string[] cats = { "Kiky", "Mary", "Lily", "Garfield" }; 3 public IEnumerator GetEnumerator() { 4 return new CatEnumerator(cats); 5 } 6 } 7 class CatEnumerator : IEnumerator { 8 private string[] _cats = null; 9 public CatEnumerator(string[] cats) { 10 _cats = cats; 11 } 12 private int index = -1; 13 public object Current { 14 get { return _cats[index]; } 15 } 16 public bool MoveNext() { 17 if (++index < _cats.Length) { 18 return true; 19 } else { 20 return false; 21 } 22 } 23 public void Reset() { 24 index = -1; 25 } 26 } 27 private void Button_Click_3(object sender, RoutedEventArgs e) { 28 CatArray cats = new CatArray(); 29 foreach (string cat in cats) { 30 tb3.Text += cat + ","; 31 } 32 }