c# Yield return之简单方法实现迭代器和集合初始化器

来源:互联网 发布:建筑图js 编辑:程序博客网 时间:2024/04/28 12:52

背景:最近看 C# in Depth ,谈到初始化器的时候上面说是主要看类中的Add方法,当时第一感觉是有这么神奇,有这个方法就能实现初始化器?然后我就自己写了一个只有Add()的List,初始化的时候提示要实现IComarable,想到这本书中还谈到一个简单的方法:用yield return实现用这个接口来完成迭代器功能,一举两得,学习两个知识点。

注:List代码主要是利用了微软的原代码:http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646

第一版

class MyList<T>    {        private const int _defaultCapacity = 4;        private T[] _items;        private int _size;        static readonly T[] _emptyArray = new T[0];        public MyList()        {            _items = _emptyArray;        }        public int Capacity        {            get            {                return _items.Length;            }            set            {                if (value < _size)                    throw new ArgumentOutOfRangeException("value");                if (value != _items.Length)                {                    if (value > 0)                    {                        T[] newItems = new T[value];                        if (_size > 0)                        {                            Array.Copy(_items, 0, newItems, 0, _size);                         }                        _items = newItems;                    }                    else                    {                        _items = _emptyArray;                    }                }            }        }        public void Add(T item)        {            if (_size == _items.Length)                EnsureCapacity(_size + 1);            _items[_size++] = item;        }        private void EnsureCapacity(int min)        {            if (_items.Length < min)            {                int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Length * 2;                //if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;                if (newCapacity < min) newCapacity = min;                Capacity = newCapacity;            }        }}static void Main(string[] args)        {            MyList<string> myList = new MyList<string> { "asdf ", "dfa" };            Console.ReadKey();        }
运行的时候会提示:无法使用集合初始舒畅一初始化类型,原因是它未实现”System.Colletions.IEnumberable”。

第二版:主要是实现了System.Colletions.IEnumberable接口


class MyList<T> : IEnumerable{……//同上段代码  public Enumerator GetEnumerator()        {            return new Enumerator(this);        }        IEnumerator<T> IEnumerable<T>.GetEnumerator()        {            return new Enumerator(this);        }        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()        {            return new Enumerator(this);        }        public struct Enumerator : IEnumerator<T>, IEnumerator        {            private MyList<T> list;            private int index;            private T current;            public Enumerator(MyList<T> list)            {                this.list = list;                index = 0;                current = default(T);            }            public void Dispose()            { }            public bool MoveNext()            {                MyList<T> localList = list;                if ((uint)index < (uint)localList._size)                {                    current = localList._items[index];                    index++;                    return true;                }                return MoveNextRare();            }            private bool MoveNextRare()            {                index = list._size + 1;                current = default(T);                return false;            }            public T Current            {                get                {                    return current;                }            }            object IEnumerator.Current            {                get                {                    return current;                }            }            void IEnumerator.Reset()            {                index = 0;                current = default(T);            }}

初始化器和迭代功能都可以正常使用

第三版:使用yield return完成迭代器功能

注:将上段实现迭代器代码全部用下面代码替代

 public IEnumerator GetEnumerator()        {            return new Enumerator(this).GetEnumerator();        }        public struct Enumerator : IEnumerable        {            private MyList<T> list;            private int index;            private T current;            public Enumerator(MyList<T> list)            {                this.list = list;                index = 0;                current = default(T);            }            public void Dispose()            { }            public IEnumerator GetEnumerator()            {                for (int index = 0; index < list._size; index++)                {                    yield return current = list._items[index];                }            }      }

另外如果把Add方法改名会提示:并不包含“Add”的定义

结论:yield return可以简单地实现迭代功能,大大的简化了代码,具体的奥秘还得深入学习。





0 0
原创粉丝点击