List of enumerators?

  • Thread starter Thread starter A.B.
  • Start date Start date
A

A.B.

Hi,
I have various lists I want to go through, at different paces and I
want to control that with a list of enumerators.

I have the following:

List<List<DataEntry>> mydata = new List<List<Data>>();
List<List<DataEntry>.Enumerator> myenums = news
List<List<Data>.Enumertor>();

I do
myenums.Add(mydata[0].GetEnumerator());
then
myenums[0].MoveNext();

well it seems that doesn't work... like myenums[0] is a temporary copy
of the enumerator... I don't know but when I do that, myenums[0]
desn't actually move.

e = myenums[0];
e.MoveNext();

works though, meaning e moves, but it doesn't change myenums[0]
( !?? )

Can someone explain me the rational here and a good way to do what I
am trying to achieve?
Thanks!
 
A.B. said:
Hi,
I have various lists I want to go through, at different paces and I
want to control that with a list of enumerators.

I have the following:

List<List<DataEntry>> mydata = new List<List<Data>>();
List<List<DataEntry>.Enumerator> myenums = news
List<List<Data>.Enumertor>();

I do
myenums.Add(mydata[0].GetEnumerator());
then
myenums[0].MoveNext();

well it seems that doesn't work... like myenums[0] is a temporary copy
of the enumerator... I don't know but when I do that, myenums[0]
desn't actually move.

e = myenums[0];
e.MoveNext();

works though, meaning e moves, but it doesn't change myenums[0]
( !?? )

Can someone explain me the rational here and a good way to do what I
am trying to achieve?
Thanks!

What you are experiencing is the usage of a value type. An enumerator is
a structure, which means that whenever you get the enumerator from the
list, you are getting a copy of it. If you want the enumerator in the
list to be updated, you have to put the updated enumerator back into the
list:

e = myenums[0];
e.MoveNext();
myenums[0] = e;
 
Here's a working code showing what happens


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<List<int>> l = new List<List<int>>();
List<List<int>.Enumerator> e = new
List<List<int>.Enumerator>();

l.Add(new List<int>());
l.Add(new List<int>());

l[0].Add(1);
l[0].Add(2);
l[1].Add(10);
l[1].Add(11);

e.Add(l[0].GetEnumerator());
e.Add(l[1].GetEnumerator());

e[0].MoveNext();
Console.WriteLine(e[0].Current); // prints 0, I'd like to
print "1"
List<int>.Enumerator f = e[1];
f.MoveNext(); f.MoveNext();
Console.WriteLine("{0} {1}",f.Current,e[1].Current); //
prints 11 0, I'd like to print "11 11"
}
}
}
 
A.B. said:
List<List<DataEntry>> mydata = new List<List<Data>>();
List<List<DataEntry>.Enumerator> myenums = news
myenums.Add(mydata[0].GetEnumerator());

myenums[0].MoveNext();

List<T>.Enumerator is a value type, so myenums[0] will return a copy.
Cast it to IEnumerable<T> instead.

-- Barry
 
What you are experiencing is the usage of a value type. An enumerator is
a structure, which means that whenever you get the enumerator from the
list, you are getting a copy of it.

Note that enumerators aren't *in general* structures. It just happens
that List<T>.Enumerator is a structure.

That's a pretty nasty "gotcha" when converting from .NET 1.1 to
generics...

Jon
 
List<T>.Enumerator is a value type, so myenums[0] will return a copy.
Cast it to IEnumerable<T> instead.

Could you show me how I'd do that on the sample code I posted?
Thanks!
 
A.B. said:
List<T>.Enumerator is a value type, so myenums[0] will return a copy.
Cast it to IEnumerable<T> instead.

Could you show me how I'd do that on the sample code I posted?
Thanks!

You only need to change the declarations for e and f:

List<IEnumerator<int>> e = new List<IEnumerator<int>>();
and
IEnumerator<int> f = e[1];

Then it works as per your comments.
 
A.B. said:
Hi,
I have various lists I want to go through, at different paces and I
want to control that with a list of enumerators.

I have the following:

List<List<DataEntry>> mydata = new List<List<Data>>();
List<List<DataEntry>.Enumerator> myenums = news
List<List<Data>.Enumertor>();

I do
myenums.Add(mydata[0].GetEnumerator());
then
myenums[0].MoveNext();

well it seems that doesn't work... like myenums[0] is a temporary copy
of the enumerator... I don't know but when I do that, myenums[0]
desn't actually move.

Correct. Accessing an item inside a List always returns a temporary copy,
while access to an array element is in-place. For reference types, a copy
of the reference means you end up working on the same object in the end, but
with value types, a copy is completely independent.
 
Tried it but

e.Add(l[0].GetEnumerator());

fails

Error 1 The best overloaded method match for
'System.Collections.Generic.List<System.Collections.Generic.IEnumerable<int>>.Add(System.Collections.Generic.IEnumerable<int>)'
has some invalid arguments

and

e.Add((IEnumerable<int>)l[0].GetEnumerator());

fails too

Error 1 Cannot convert type
'System.Collections.Generic.List<int>.Enumerator' to
'System.Collections.Generic.IEnumerable<int>'
 
A.B. said:
Tried it but

e.Add(l[0].GetEnumerator());

fails

Error 1 The best overloaded method match for
'System.Collections.Generic.List<System.Collections.Generic.IEnumerable<int>>.Add(System.Collections.Generic.IEnumerable<int>)'
has some invalid arguments

I made a couple of mistakes, you should instantiate:

List<IEnumerator<int>>

rather than:

List<IEnumerable<int>>

Sorry.

-- Barry
 
A.B. said:
Here's a working code showing what happens


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<List<int>> l = new List<List<int>>();
List<List<int>.Enumerator> e = new
List<List<int>.Enumerator>();

l.Add(new List<int>());
l.Add(new List<int>());

l[0].Add(1);
l[0].Add(2);
l[1].Add(10);
l[1].Add(11);

e.Add(l[0].GetEnumerator());
e.Add(l[1].GetEnumerator());

e[0].MoveNext();

As I said, you are getting a copy of the enumerator. If you want the
enumerator in the list to change, you have to put the enumerator that
you changed back in the list:

Enumerator en = e[0];
en.MoveNext();
e[0] = en;
Console.WriteLine(e[0].Current); // prints 0, I'd like to
print "1"
List<int>.Enumerator f = e[1];
f.MoveNext(); f.MoveNext();
Console.WriteLine("{0} {1}",f.Current,e[1].Current); //
prints 11 0, I'd like to print "11 11"
}
}
}
 
As I said, you are getting a copy of the enumerator. If you want the
enumerator in the list to change, you have to put the enumerator that
you changed back in the list:

Enumerator en = e[0];
en.MoveNext();
e[0] = en;

Or make the list a list of boxed versions which can be used directly
via an interface, in which case there's no need to replace anything -
the value inside the box changes instead.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top