Implementing C# IEnumerable<T> for a LinkedList class
c#, mono, monodevelop
Solution
You need to add the non-generic APIs; so add to the iterator:
object System.Collections.IEnumerator.Current { get { return Current; } }
and to the enumerable:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
HOWEVER! If you are implementing this by hand, you are missing a trick. An "iterator block" would be much easier.
The following is a complete implementation; you don't need to write an enumerator class at all (you can remove `myLinkedListIterator<T>` completely):
public IEnumerator<T> GetEnumerator()
{
var node = front;
while(node != null)
{
yield return node.data;
node = node.next;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
Problem
I'm trying to write a custom LinkedList class in C# using monoDevelop on Linux, just for the sake of testing and learning. The following code never compiles, and I have no idea why!! It doesn't even tell me what's wrong. All what it says is: Error: The compiler appears to have crashed. Check the build output pad for details. When I go to check the output pad, it's not helpful either: Unhandled Exception: System.ArgumentException: The specified field must be declared on a generic type definition. Parameter name: field What can I do? ``` using System; using System.Text; using System.Collections.Generic; namespace LinkedList { public class myLinkedList<T> : IEnumerable<T> { //List Node class //=============== private class ListNode<T> { public T data; public ListNode<T> next; public ListNode(T d) { this.data = d; this.next = null; } public ListNode(T d, ListNode<T> n) { this.data = d; this.next = n; } } //priavte fields //=============== private ListNode<T> front; private int size; //Constructor //=========== public myLinkedList () { front = null; size = 0; } //public methods //=============== public bool isEmpty() { return (size == 0); } public bool addFront(T element) { front = new ListNode<T>(element, front); size++; return true; } public bool addBack(T element) { ListNode<T> current = front; while (current.next != null) { current = current.next; } current.next = new ListNode<T>(element); size++; return true; } public override string ToString() { ListNode<T> current = front; if(current == null) { return "**** Empty ****"; } else { StringBuilder sb = new StringBuilder(); while (current.next != null) { sb.Append(current.data + ", "); current = current.next; } sb.Append(current.data); return sb.ToString(); } } // These make myLinkedList<T> implement IEnumerable<T> allowing // a LinkedList to be used in a foreach statement. public IEnumerator<T> GetEnumerator() { return new myLinkedListIterator<T>(front); } private class myLinkedListIterator<T> : IEnumerator<T> { private ListNode<T> current; public virtual T Current { get { return current.data; } } private ListNode<T> front; public myLinkedListIterator(ListNode<T> f) { front = f; current = front; } public bool MoveNext() { if(current.next != null) { current = current.next; return true; } else { return false; } } public void Reset() { current = front; } public void Dispose() { throw new Exception("Unsupported Operation"); } } } } ```