Proposal: allow IEnumerator on foreach loop

C

cody

Currently it is only legal to use types which has a method named
GetEnumerator to be used in a foreach loop.
This makes it impossible to use the same Enumerator after and before a
foreach loop, because GetEnumerator always returns a new one.

My proposal would allow the following scenario:

You could for example the first and the last element of the list as a
special case:

ArrayList l = new ArrayList();
l.Add(1);
l.Add(2);
l.Add(3);

IEnumerator e = l.GetEnumerator();

if (e.MoveNext())
{
object first = e.current;
// do something with first element
}

// reuse enumerator from above, note that iteration starts with second
// element, not the first, unless we call Reset on the enumerator.
foreach object i in e)
{
// do something
}

object last = e.Current; // current still points to last element
// do something with the last element
 
J

Jon Skeet [C# MVP]

Currently it is only legal to use types which has a method named
GetEnumerator to be used in a foreach loop.
This makes it impossible to use the same Enumerator after and before a
foreach loop, because GetEnumerator always returns a new one.

Rather than making a language change, why not create your own
IEnumerable implementation which is simply given an IEnumerator which
it always returns?

Note that for first/last special casing, you could use my
SmartEnumerable:
http://www.yoda.arachsys.com/csharp/miscutil/usage/smartenumerable.html

Jon
 
C

cody

Jon said:
Rather than making a language change, why not create your own
IEnumerable implementation which is simply given an IEnumerator which
it always returns?

Note that for first/last special casing, you could use my
SmartEnumerable:
http://www.yoda.arachsys.com/csharp/miscutil/usage/smartenumerable.html

Jon

Yes I've read your blog, that's what gave me the idea in the first
place.. :)
Your enumerable is a good idea, but brings performance penalties with it.
One could also invent an operator which yields not the elements but the
indices of a given collection, which also allows one to use the index
within the foreach loop, which could also be used for determining the
first and last element.
Making that GetIndexEnumerator() an extension method in C# 3 would be
very nice. The more I thing about extension methods the more I love em.

A foreach accepting an IEnumerator would have the advantage that you
could reuse it to save resources (If creating enumerator is a
performance neck e.g. a serverside database cursor has to be opened, or
whatever). I mean, what is Reset() good for when you cannot use it,
unless you do the loop manually, without using foreach?
 
J

Jon Skeet [C# MVP]

Yes I've read your blog, that's what gave me the idea in the first
place.. :)
:)

Your enumerable is a good idea, but brings performance penalties with it.

Have you got a situation where those performance penalties are
significant?
In the case of my suggestion of an IEnumerable which just returned the
original IEnumerator, the performance penalty would be absolutely
*tiny*!
One could also invent an operator which yields not the elements but the
indices of a given collection, which also allows one to use the index
within the foreach loop, which could also be used for determining the
first and last element.

Do you mean like Enumerable.Range in .NET 3.5? (I'm working on a
generic Range class as part of my book, btw.)
Making that GetIndexEnumerator() an extension method in C# 3 would be
very nice. The more I thing about extension methods the more I love em.

A foreach accepting an IEnumerator would have the advantage that you
could reuse it to save resources (If creating enumerator is a
performance neck e.g. a serverside database cursor has to be opened, or
whatever). I mean, what is Reset() good for when you cannot use it,
unless you do the loop manually, without using foreach?

If you really, really need the performance, just write the foreach
loop manually.
I suspect that it's *very* rare that the overhead introduced by
something like SmartEnumerable (or the other solution suggested here)
would be significant - definitely not common enough to be worth
requiring a language change.

(As for what Reset is good for - very little, IMO. It's often
unimplemented, and was probably a mistake in hindsight.)

Jon
 

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

Top