如何使用 IEnumerable、IEnumerator 制作自定义链表

How to make a custom Linked List using IEnumerable, IEnumerator

我正在尝试创建一个允许我迭代每个元素的简单链表。

但是当我尝试在方法 GetReservation() 上迭代列表时,foreach 立即停止,我不明白为什么。

我假设 'this' 指令 returns class 的可枚举部分。

但我不确定。

我需要一些帮助才能弄明白。

public class Reservation
    {
        public string reference;
        public string client;
        public string state;



        public Reservation(string reference, string client, string state)
        {
            this.reference = reference;
            this.client = client;
            this.state = state;
        }

        public Reservation()
        {
        }

        public override bool Equals(object obj)
        {
            return obj is Reservation reservation &&
                   reference == reservation.reference &&
                   client == reservation.client &&
                   state == reservation.state;
        }


    }
public class Row
    {
        public Reservation reservation;
        public Row nextRow;

    }
public class Lista : IEnumerable, IEnumerator
    {
        private Row _header;
        private Row Current;
        private int counter;

        public Lista()
        {
            _header = Current = null;
            counter = 0;
        }

        public bool MoveNext()
        {
            if (Current.nextRow != null)
            {
                Current = Current.nextRow;
                return true;
            }
            else
            {
                return false;
            }
        }

        public void Reset()
        {
            Current = _header;
        }

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public IEnumerator GetEnumerator()
        {
            return this;
        }

        public void Add(Reservation data)
        {
            Row newRow = new Row();
            newRow.reservation = data;
            if (counter == 0)
            {
                _header = Current = newRow;
            } else
            {
                Current.nextRow = newRow;
                Current = newRow;
            }
            counter++;
        }

        public Reservation GetReservation(int index)
        {
            int x = 0;

            foreach (Row row in this)
            {
                if (x == index)
                {
                    return row.reservation;
                }
                x++;
            }

            return null;
        }

        public Reservation Remove(Reservation data)
        {
            Reservation reservation = null;
            if (_header.reservation.Equals(data)){
                reservation = _header.reservation;
                _header = _header.nextRow;
            } else
            {
                foreach (Row row in this)
                {
                    if (row.nextRow.reservation.Equals(data))
                    {
                        if(row.nextRow.nextRow == null)
                        {
                            reservation = row.nextRow.reservation;
                            row.nextRow = null;
                        } else
                        {
                            reservation = row.nextRow.reservation;
                            row.nextRow = row.nextRow.nextRow;
                        }
                    }
                }
            }

            if (reservation != null)
            {
                counter--;
            }

            return reservation;
            
            
        }
    }
  1. 您需要 IEnumerable 实现 return 新 class 的新实例 ListEnumerator : IEnumerator 这样 ListEnumerator 将具有 Current因此 ListEnumerator 的不同实例可以独立地迭代列表实例。
  2. 你最好实现通用版本,例如IEnumerable<T>IEnumerator<T>

通常 IEnumerator 实现是一个私有的 class 嵌套在 IEnumerable 实现下,它有一个数据成员指向 IEnumerable 实现的实例迭代。

主要问题是链表和枚举器出于不同目的共享当前行。

当调用Add方法时,Current被设置为链表最后一项的新行。

GetReservation 中的 foreach 块调用 GetEnumerator,其中 returns 此列表的实例。但是列表的当前行是最后添加的行。因此,当在迭代期间调用 MoveNext 时,返回 false,因为最后一行没有下一行。循环结束。

要解决此问题,最好创建一个单独的 class 来实现 IEnumerator,例如

public class Lista : IEnumerable
{
    ...

    GetEnumerator() 
    {
        return new ListaEnumerator(_header);
    }

    private class ListaEnumerator : IEnumerator
    {
        private Row _current;

        public ListaEnumerator(Row header)
        {
            _current = header;
        }

        ...

    }
}

这样就可以有几个互不影响或列表的枚举器。