泛型枚举IEnumerable<T>与泛型迭代IEnumerator<T>

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();
        }
    }

泛型枚举与泛型迭代先到这了...如果有哪里不正确的地方还请大家指出.谢谢

原文地址:https://www.cnblogs.com/aaronguo/p/2626992.html