C# 自己实现IEnumerable接口来实现foreach遍历

实现了IEnumerable接口的集合才可以使用foreach

如何进行foreach是通过IENumerable下的GetEnumerable方法来实现的。

这个方法需要一个IEnumerator对象

这个对象的这些方法就决定了怎么样去遍历你定义的集合

如下图是自己定义的LinkedList需要自己去实现下面这个方法。

 I

 IEnumerator IEnumerable.GetEnumerator()
        {
            return new ListEnum(this);
        }

这个对象我们可以实现IEnumerator接口,然后实现方法就可以了。

public struct ListEnum : IEnumerator, IEnumerator<T>
        {
            private LinkedList<T> list;
            int posistion;
            //当前值,只读
            object IEnumerator.Current
            {
                get
                {
                    try
                    {
                        return list.FindByIndex(posistion).item;
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }

            public T Current
            {
                get
                {
                    try
                    {
                        var temp = list.FindByIndex(posistion).item;
                        return list.FindByIndex(posistion).item;
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
            //构造将你的集合拿过来
            public ListEnum(LinkedList<T> list)
            {
                posistion = -1;
                this.list = list;
            }
            //每次遍历时做的事,以及何时停止遍历
            public bool MoveNext()
            {
                posistion++;
                return posistion<=list.Count;
            }
            public void Reset()
            {
                posistion = -1;
            }

            public void Dispose()
            {
            }
        }

我们将链表从头到尾的遍历一遍。

完整代码如下

using Google.ProtocolBuffers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace GrapeCity.Winston.LinkedList
{
    public class LinkedList<T> : object, IList<T>
    {
        internal LinkedListNode<T> Head;
        private EqualityComparer<T> compare = EqualityComparer<T>.Default;

        int Count { get; set; }
        int ICollection<T>.Count
        {
            get
            {
                return Count;
            }
        }
        //index
        public T this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public bool IsReadOnly
        {
            get 
            {
                return true;
            }
        }

        public LinkedList()
        {
            Count = 0;
        }

        public LinkedList(IEnumerable<T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }

            foreach (T item in collection)
            {

            }
        }

        public LinkedListNode<T> GetHead()
        {
            return this.Head;
        }

        public void Add(T item)
        {
            if (Head == null)
            {
                Head = new LinkedListNode<T>(item);
            }
            else
            {
                LinkedListNode<T> lastNode = FindLastNode();
                InternalInsertNodeAfter(lastNode, new LinkedListNode<T>(item));
            }
        }
        //往节点后添加一个新节点
        public void AddAfter(LinkedListNode<T> node, T value)
        {
            LinkedListNode<T> result = new LinkedListNode<T>(value);
            InternalInsertNodeAfter(node.Next, result);
        }

        //把newNode插入到node前面
        private void InternalInsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            newNode.Next = node;
            newNode.Prev = node.Prev;
            node.Prev.Next = newNode;
            node.Prev = newNode;
            Count++;
        }
        //把newNode插入到node后面
        private void InternalInsertNodeAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
        {
            newNode.Prev = node;
            newNode.Next = null;
            node.Next = newNode;
            Count++;
        }
        public LinkedListNode<T> FindLastNode()
        {
            LinkedListNode<T> index = Head;
            while (index.Next != null)
            {
                index = index.Next;
            }
            return index;
        }

        //根据item的值来查找到多个节点
        public LinkedListNode<T> Find(T value)
        {

            LinkedListNode<T> index = Head;
            while (index != null && value != null)
            {
                if (compare.Equals(index.item, value))
                {
                    return index;
                }
                index = index.Next;
            }

            return null;
        }
        public LinkedListNode<T> FindByIndex(int listIndex)
        {
            var temp = this.GetHead();
            for (int index = 0; index <= listIndex && temp != null; index++)
            {
                if (index == listIndex)
                {
                    return temp;
                }
                temp = temp.Next;
            }
            return null;
        }

        public void Clear()
        {
            LinkedListNode<T> current = Head;
            while (current != null)
            {
                var temp = current;
                current = current.Next;
                temp.Invalidate();
            }
            Head = null;
            Count = 0;
        }



        public bool Contains(T item)
        {
            throw new NotImplementedException();
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }



        public int IndexOf(T item)
        {
            throw new NotImplementedException();
        }

        //根据下标添加
        public void Insert(int index, T item)
        {
            var findNode = FindByIndex(index);
            InternalInsertNodeBefore(findNode, new LinkedListNode<T>(item));
        }

        public bool Remove(T item)
        {
            LinkedListNode<T> node = Find(item);
            while (node != null)
            {
                RemoveFirst(node);
            }
            return true;
        }
        public void RemoveFirst(T item)
        {
            var node = Find(item);
            RemoveFirst(node);
        }

        public void RemoveFirst(LinkedListNode<T> node)
        {
            //删除头结点
            if (node == Head)
            {
                Head = Head.Next;
            }
            //删除尾节点
            else if (node.Next == null)
            {
                node.Prev.Next = null;
                node.Prev = null;
            }
            //删除中间节点
            else
            {
                node.Next.Prev = node.Prev;
                node.Prev.Next = node.Next;
            }
            node.Invalidate();
            Count--;
        }

        public void RemoveAt(int index)
        {
            var removeNode = FindByIndex(index);
            RemoveFirst(removeNode);
        }
        //需要Ienumerator对象来定义foreach遍历的规则
        public IEnumerator<T> GetEnumerator()
        {
            return new ListEnum(this);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new ListEnum(this);
        }

        public class LinkedListNode<T>
        {
            internal LinkedListNode<T> Next;
            internal LinkedListNode<T> Prev;
            internal T item;

            public LinkedListNode(T value)
            {
                this.item = value;
            }

            public override string ToString()
            {
                return $"{this.item}";
            }

            internal void Invalidate()
            {
                Next = null;
                Prev = null;
            }
        }
        //TODO 用于遍历,记得删除
        public void WatchLinkedList<T>()
        {
            StringBuilder str = new StringBuilder();
            var index = this.GetHead();
            while (index != null)
            {
                str.Append(index.ToString());
                str.Append(" ");
                index = index.Next;
            }
            Console.WriteLine(str);
        }


        public struct ListEnum : IEnumerator, IEnumerator<T>
        {
            private LinkedList<T> list;
            int posistion;
            object IEnumerator.Current
            {
                get
                {
                    try
                    {
                        return list.FindByIndex(posistion).item;
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }

            public T Current
            {
                get
                {
                    try
                    {
                        var temp = list.FindByIndex(posistion).item;
                        return list.FindByIndex(posistion).item;
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }

            public ListEnum(LinkedList<T> list)
            {
                posistion = -1;
                this.list = list;
            }

            public bool MoveNext()
            {
                posistion++;
                return posistion<=list.Count;
            }
            public void Reset()
            {
                posistion = -1;
            }

            public void Dispose()
            {
            }
        }
    }

}

这样我们就实现了一个非常简单的链表。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值