如何使用 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;
}
}
- 您需要
IEnumerable
实现 return 新 class 的新实例 ListEnumerator : IEnumerator
这样 ListEnumerator
将具有 Current
因此 ListEnumerator
的不同实例可以独立地迭代列表实例。
- 你最好实现通用版本,例如
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;
}
...
}
}
这样就可以有几个互不影响或列表的枚举器。
我正在尝试创建一个允许我迭代每个元素的简单链表。
但是当我尝试在方法 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;
}
}
- 您需要
IEnumerable
实现 return 新 class 的新实例ListEnumerator : IEnumerator
这样ListEnumerator
将具有Current
因此ListEnumerator
的不同实例可以独立地迭代列表实例。 - 你最好实现通用版本,例如
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;
}
...
}
}
这样就可以有几个互不影响或列表的枚举器。