Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I get a value of Current When I implemented IEnumerable?

I did below work

class Program
{
    class GenEnumerator<T> : IEnumerable
    {
        public T[] Values { get; set; }


        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < Values.Length; i++)
                yield return Values[i];
        }
    }

    static void Main(string[] args)
    {
        GenEnumerator<string> g = new GenEnumerator<string>();
        g.Values = new string[] { "a", "b", "c", "d", "e" };
        g.GetEnumerator().MoveNext();

        Console.WriteLine(g.GetEnumerator().Current);


        Console.ReadKey();
    }
}

g.GetEnumerator().Current is always null.
but if I do this - var a = g.GetEnumerator();
the Current proeperty gets a value and works fine

Does it imply that I have to explicitly inherit the class from IEnumerator and implement its methods and property if I want to use Current without a IEnumerator type variable?

Thanks, Roy

like image 684
Roybot Avatar asked Jan 08 '14 09:01

Roybot


People also ask

What is current in IEnumerator interface?

The element in the collection at the current position of the enumerator. The following code example demonstrates the implementation of the IEnumerator interfaces for a custom collection. In this example, Current is not explicitly called, but it is implemented to support the use of foreach ( for each in Visual Basic).

What is return in IEnumerable?

Returns an enumerator that iterates through a collection. An IEnumerator object that can be used to iterate through the collection. The following code example demonstrates the implementation of the IEnumerable interfaces for a custom collection.

What is IEnumerable GetEnumerator?

An IEnumerator object that can be used to iterate through the collection. The following code example demonstrates the implementation of the IEnumerable interfaces for a custom collection. In this example, GetEnumerator is not explicitly called, but it is implemented to support the use of foreach ( For Each in Visual Basic).

Does IEnumerable remember the current state it was processing?

As per code, we are now passing IEnumerable. Let's check out the output: As per output, it is clear that IEnumerable does not remember the current state it was processing. Thus it starts processing back from the 1st index. In this article, we learned how to and when to use IEnumerable & IEnumerator.


2 Answers

You're creating new instances of GenEnumerator everytime by calling GetEnumerator, that's why your Current is null. Instead store it in a field and use that.

var e = g.GetEnumerator();
if(e.MoveNext())
{
    var current = e.Current;
}
like image 59
Sriram Sakthivel Avatar answered Oct 12 '22 19:10

Sriram Sakthivel


This is because in order for the Current to become non-null, you need to call MoveNext() on the same object.

Your current code calls MoveNext() on a temporary object. Here is what's going on when you call

g.GetEnumerator().MoveNext()`;
Console.WriteLine(g.GetEnumerator().Current);
  • A call of GetEnumerator() returns an object x
  • A call x.MoveNext() is performed
  • x becomes eligible for garbage collection, because it is not referenced from any variable in your program.
  • When you call g.GetEnumerator().Current, a new object y is returned
  • A call to y.Current is made, returning null, because there was no call of MoveNext on object y

When you add a variable a, however, you call MoveNext and Current on the same object, fixing the problem:

  • A call of GetEnumerator() returns an object x, which is assigned to variable a
  • A call a.MoveNext() is performed
  • A call a.Current is performed
like image 7
Sergey Kalinichenko Avatar answered Oct 12 '22 19:10

Sergey Kalinichenko