I'm new to C# programming, I was experimenting with iterators concept in C#. Here, I'm trying to display all the terms in a list, for that I'm trying different ways to obtain the results. In the below code, I'm using two classes ListIterator and ImplementList.
In the ListIterator class
: I defined a HashSet
and it uses IEnumerator
to store the values. Here GetEnumerator()
method returns the values in the list. GetEnumerator is implemented in the ImplementList class
(other class). Finally, the list is displayed in the console.
public class ListIterator
{
public void DisplayList()
{
HashSet<int> myhashSet = new HashSet<int> { 30, 4, 27, 35, 96, 34};
IEnumerator<int> IE = myhashSet.GetEnumerator();
while (IE.MoveNext())
{
int x = IE.Current;
Console.Write("{0} ", x);
}
Console.WriteLine();
Console.ReadKey();
}
}
In the ImplementList class : GetEnumerator()
is defined and it returns the list using yield return x.
public class ImplementList : IList<int>
{
private List<int> Mylist = new List<int>();
public ImplementList() { }
public void Add(int item)
{
Mylist.Add(item);
}
public IEnumerator<int> GetEnumerator()
{
foreach (int x in Mylist)
yield return x;
}
}
Now, I want to rewrite the GetEnumerator()
without using yield return
. And it should return all the values in a list. I tried using for loop as for(int x=0; x<Mylist.Count; x++)
, but it doesn't return all the values in the list.
Is it possible to get all the values in the list without using yield return
in IEnumerator
1 Answer 1
MoveNext()
is a method that is called over and over and every time it has to move to the next item. This means you can't implement it by simply using a for
loop (unless you use yield return
, which is pretty much the reason why yield return
exists), you need to rewrite it so that each MoveNext()
call executes just part of that loop.
Specifically, it would look like this:
class Enumerator : IEnumerator<int>
{
private int i = -1;
private ImplementList list;
public Enumerator(ImplementList list)
{
this.list = list;
}
public bool MoveNext()
{
i++;
return i < list.myList.Count;
}
public int Current { get { return list.myList[i]; } }
object IEnumerator.Current { get { return Current; } }
public void Dispose() {}
public void Reset() { throw new NotSupportedException(); }
}
This way, every call to MoveNext()
performs the i++
and i < list.Count
parts of the for
loop.
-
Will that work with my for loop, I mean (for(int x=0; x<Mylist.count; x++))..giri– giri2014年07月21日 19:45:48 +00:00Commented Jul 21, 2014 at 19:45
-
@GIRI You mean when
Mylist
isImplementList
? No, why would that useIEnumerable
orIEnumerator
? You're just incrementing an integer.svick– svick2014年07月21日 19:50:37 +00:00Commented Jul 21, 2014 at 19:50 -
So, when a GetEnumerator is invoked. How we are going to return the values?giri– giri2014年07月21日 19:54:42 +00:00Commented Jul 21, 2014 at 19:54
-
@GIRI
GetEnumerator()
is invoked either when you useforeach
or when you manually call it (though this is very rare in normal code). If you want to use your collection in afor
loop, you should write an indexer, and possibly also implement something likeIList<T>
orIReadOnlyList<T>
.svick– svick2014年07月21日 19:57:36 +00:00Commented Jul 21, 2014 at 19:57 -
I'm a learner, can you please give a clear explanation. @svickgiri– giri2014年07月21日 20:06:01 +00:00Commented Jul 21, 2014 at 20:06
yield
you may want to take a look at this MSDN code example. But in real scenario it would probably be better to justreturn MylList.GetEnumerator()
- much more clear and effective than both theyield
and custom enumerator.