I'm trying to create a simple Linked List that allows me to iterate each element.
But when I try to iterate the list on the method GetReservation() the foreach imidiatly stops and I don't understand why.
I supose that 'this' instruction returns the Enumerable part of the class.
But I'm not sure.
I need some help to figure it out.
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;
}
}
The main issue is that both the linked list and the enumerator share the current row for different purposes.
When the Add
method is called, Current
is set to the new row which is the last item of the linked list.
The foreach
block in GetReservation
calls GetEnumerator
which returns the instance of this list. But the current row of the list is the last added row. So when MoveNext
is called during the iteration, false
is returned since the last row has no next row. That ends the loop.
To solve this problem it is best to create a separate class which implements IEnumerator
e.g.
public class Lista : IEnumerable
{
...
GetEnumerator()
{
return new ListaEnumerator(_header);
}
private class ListaEnumerator : IEnumerator
{
private Row _current;
public ListaEnumerator(Row header)
{
_current = header;
}
...
}
}
This way it is possible to have several enumerators that do not affect each other or the list.