extended foreach loop

  • Thread starter Thread starter cody
  • Start date Start date
C

cody

currently, foreach takes a IEnumerable as parameter, so we can do:

foreach (int i in array){}

what about an additional form of foreach that takes an IEnumerator as
parameter, so we can do:

foreach (int i in array.SkipIterator(2)) // get every 2nd item

or

foreach (int i in array.RangeIterator(2, 10)) // iterates items from 2 to 10

or

foreach (int i in array.ReverseIterator()) // iterates through items in
reverse order

or

foreach (int i in array.SafeIterator(typeof(int))) // iterates through all
items that are != null and are of type int

What do you think? I always wanted such a thing since foreach with iterators
are much better readable as a for loops and the intend is much clearer.
 
Hi

I don't think so :-)

For Each means, for "each". That doesn't mean that you should be able to
skip items.

Kind regards

Alexander
 
cody said:
currently, foreach takes a IEnumerable as parameter, so we can do:

foreach (int i in array){}

what about an additional form of foreach that takes an IEnumerator as
parameter, so we can do:

foreach (int i in array.SkipIterator(2)) // get every 2nd item

or

foreach (int i in array.RangeIterator(2, 10)) // iterates items from 2 to 10

or

foreach (int i in array.ReverseIterator()) // iterates through items in
reverse order

or

foreach (int i in array.SafeIterator(typeof(int))) // iterates through all
items that are != null and are of type int

What do you think? I always wanted such a thing since foreach with iterators
are much better readable as a for loops and the intend is much clearer.

You could easily write your own class to do that though:

foreach (int i in new SkipIterator(array, 2))
{
}

foreach (int i in new SafeIterator(array, typeof(int)))
{
}

etc
 
Alexander Muylaert said:
Hi

I don't think so :-)

For Each means, for "each". That doesn't mean that you should be able to
skip items.

Kind regards

Alexander

I think what cody is asking for is completely reasonable. I do not think,
however, that we should have language-level support for this since it is
(almost) trivial to implement it in terms of what we already have in the
language. E.g., (WARNING: UNTESTED CODE):

public class SkipEnumerator : IEnumerable, IEnumerator
{
IEnumerator ienumerator_;
int skip_;
bool start_ = true;

public SkipEnumerator(IEnumerable ienumerable, int skip)
{
ienumerator_ = ienumerable.GetEnumerator();
skip_ = skip;
}

#region IEnumerable

public IEnumerator GetEnumerator()
{
return this;
}

#endregion

#region IEnumerator

public bool MoveNext()
{
if (start_)
{
for (int i = 0; i < skip_; i++)
ienumerator_.MoveNext();
start_ = false;
}

return ienumerator_.MoveNext();
}

public object Current
{
get
{
return ienumerator_.Current;
}
}

public void Reset()
{
start_ = true;
ienumerator_.Reset();
}

#endregion
}

To use SkipEnumerator class, you write

int[] ints = new int[] { 1, 2, 3, 4, 5, 6, 7 };
foreach (int anInt in new SkipEnumerator(ints, 2))
{
Console.Write(anInt + " " );
}
// prints 3 4 5 6 7

RangeEnumerator and SafeEnumerator would be very similar to SkipEnumerator.
Implementing ReverseEnumerator in terms of just IEnumerator would require
two passes over the data as IEnumerator does not support moving backwards in
the data.

Regards,
Sami
 
I think what cody is asking for is completely reasonable. I do not think,
however, that we should have language-level support for this since it is
(almost) trivial to implement it in terms of what we already have in the
language. E.g., (WARNING: UNTESTED CODE):

public class SkipEnumerator : IEnumerable, IEnumerator
{
IEnumerator ienumerator_;
int skip_;
bool start_ = true;

public SkipEnumerator(IEnumerable ienumerable, int skip)
{
ienumerator_ = ienumerable.GetEnumerator();
skip_ = skip;
}

#region IEnumerable

public IEnumerator GetEnumerator()
{
return this;
}

#endregion

#region IEnumerator

public bool MoveNext()
{
if (start_)
{
for (int i = 0; i < skip_; i++)
ienumerator_.MoveNext();
start_ = false;
}

return ienumerator_.MoveNext();
}

public object Current
{
get
{
return ienumerator_.Current;
}
}

public void Reset()
{
start_ = true;
ienumerator_.Reset();
}

#endregion
}


A very good idea, I didn't think of that. An iterator which implements
IEnumerable AND IEnumerator!
That would solve my problem, and so there is indeed no need to imclude that
in the language specs.
RangeEnumerator and SafeEnumerator would be very similar to SkipEnumerator.
Implementing ReverseEnumerator in terms of just IEnumerator would require
two passes over the data as IEnumerator does not support moving backwards in
the data.

That is no problem, since internally the iterator can put out the data from
end to the beginning of the array.

Just a question: Which kind of convention is a trailing underscore for
private members? I only know conventions with leading _(_member) or leading
m_ (m_member).
 
I read the C# 2.0 language spec a couple days ago. I believe that iterator will address exactly what you suggested. you can basicly use iterator in functions that return types that implement either IEnumerator or IEnumerable. in fact, there's a example in the spec that does a reverse iterator. you can easily do skip iterator and range iterator as well

----- cody wrote: ----

currently, foreach takes a IEnumerable as parameter, so we can do

foreach (int i in array){

what about an additional form of foreach that takes an IEnumerator a
parameter, so we can do

foreach (int i in array.SkipIterator(2)) // get every 2nd ite

o

foreach (int i in array.RangeIterator(2, 10)) // iterates items from 2 to 1

o

foreach (int i in array.ReverseIterator()) // iterates through items i
reverse orde

o

foreach (int i in array.SafeIterator(typeof(int))) // iterates through al
items that are != null and are of type in

What do you think? I always wanted such a thing since foreach with iterator
are much better readable as a for loops and the intend is much clearer

-
cod

Freeware Tools, Games and Humou
http://www.deutronium.de.vu || http://www.deutronium.t
 
Just a question: Which kind of convention is a trailing underscore for
private members? I only know conventions with leading _(_member) or leading
m_ (m_member).

Oh, that's just a left-over from my C++ days. A trailing underscore was the
standard in a company I worked for many years. I don't like the 'm_' and 'm'
prefixes so I've kept the trailing underscore. I guess I should move on with
the rest of the world and change to leading underscore. Old habits die hard.

Sami
 
Daniel Jin said:
I read the C# 2.0 language spec a couple days ago. I believe that
iterator will address exactly what you suggested. you can basicly use
iterator in functions that return types that implement either IEnumerator
or IEnumerable. in fact, there's a example in the spec that does a
reverse iterator. you can easily do skip iterator and range iterator as
well.

Yes, C# 2.0 iterators will be the best solution for this. C# iterators
should also allow for easy things like predicated enumeration wrappers, etc.
 
Sami,

Underscores give me the chills. I prefer "this.skip = 10" - much easier on
the eyes and with VS, the "this" is highlighted and it becomes very easy to
figure out which variables are local or not. Also, when you type "this."
you get the popup menu.

Just MHO.

Hilton
 
Back
Top