IEnumerable<T>接口在.NET中是非常重要的接口,它允许开发人员定义foreach语句功能的实现并支持非泛型方法的简单的迭代,搭配使用的重要接口当然就是泛型迭代IEnumerator<T>,支持泛型集合上的简单迭代
命名空间:
using System.Collections.Generic;
using System.Collections;
一般的简单写法:
View Code
/// <summary> /// IEnumerable<T> -- 一般写法 /// </summary> /// <typeparam name="T"></typeparam> public class MyColl<T>:IEnumerable<T> { private T[] items; public MyColl(T[] item) { this.items = item; } public IEnumerator<T> GetEnumerator() { return new NestedEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } class NestedEnumerator:IEnumerator<T> { private MyColl<T> coll; private T current; private int index; //索引 public NestedEnumerator(MyColl<T> coll) { Monitor.Enter(coll.items.SyncRoot); this.index = -1; this.coll = coll; } public T Current { get { return current; } } public void Dispose() { try { current = default(T); index = coll.items.Length; } finally { Monitor.Exit(coll.items.SyncRoot); } } object IEnumerator.Current { get { return Current; } } public bool MoveNext() { if (++index >= coll.items.Length) { return false; } else { current = coll.items[index]; return true; } } public void Reset() { current = default(T); index = 0; } } }
IEnumerable<T>枚举器--捷径写法:
View Code
/// <summary> /// IEnumerable<T>枚举器--捷径写法 /// </summary> /// <typeparam name="T"></typeparam> public class MyCollCut<T> : IEnumerable<T> { private T[] item; public MyCollCut(T[] item) { this.item = item; } public IEnumerator<T> GetEnumerator() { return GetEnumerator(false); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// <summary> /// 接受bool型参数的GetEnumerator方法 /// </summary> /// <param name="synchronized">指示调用者是否需要一个同步或非同步的枚举器</param> /// <returns></returns> public IEnumerator<T> GetEnumerator(bool synchronized) { return( new EnumWrapper<T>(GetPrivateEnumerator(synchronized))); } private IEnumerator<T> GetPrivateEnumerator(bool synchronized) { if (synchronized) { Monitor.Enter(item.SyncRoot); } try { foreach (T i in item) { yield return i; //传入yield块方法中的参数,都被作为公共字段加入生成的枚举器类中 } } finally { if (synchronized) { Monitor.Exit(item.SyncRoot); } } } }
接受bool型参数的GetEnumerator方法:
/// <summary> /// 接受bool型参数的GetEnumerator方法 /// </summary> /// <param name="synchronized">指示调用者是否需要一个同步或非同步的枚举器</param> /// <returns></returns> public IEnumerator<T> GetEnumerator(bool synchronized) { return( new EnumWrapper<T>(GetPrivateEnumerator(synchronized))); } private IEnumerator<T> GetPrivateEnumerator(bool synchronized) { if (synchronized) { Monitor.Enter(item.SyncRoot); } try { foreach (T i in item) { yield return i; //传入yield块方法中的参数,都被作为公共字段加入生成的枚举器类中 } } finally { if (synchronized) { Monitor.Exit(item.SyncRoot); } } }
如果在遍历过程中区修改这些公共字段,必定将枚举器搞的一团糟,因此我们通过引入额外的间接层来防止这个麻烦,EnumWrapper<T>包装器,将枚举器包含在EnumWrapper<T>包装器中并返回这个包装器.
EnumWrapper<T>:
View Code
public class EnumWrapper<T> : IEnumerator<T> { private IEnumerator<T> inner; public EnumWrapper(IEnumerator<T> inner) { this.inner = inner; } public T Current { get { return inner.Current; } } public void Dispose() { inner.Dispose(); } object IEnumerator.Current { get { return inner.Current; } } public bool MoveNext() { return inner.MoveNext(); } public void Reset() { inner.Reset(); } }
泛型枚举与泛型迭代先到这了...如果有哪里不正确的地方还请大家指出.谢谢