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

背景:最近看 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值