Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Feature Request] "first:" "last:" sections in a "foreach" block

2 views
Skip to first unread message

James Curran

unread,
Apr 4, 2004, 7:19:04 AM4/4/04
to
I'd like to make the following proposal for a new feature for the C#
language. I have no connection with the C# team at Microsoft. I'm posting
it here to gather input to refine it, in an "open Source" manner, and in an
attempt to build a ground-swell of support to convince the folks at
Microsoft to add it.
Proposal: "first:" "last:" sections in a "foreach" block

The problem:
The foreach statement allows iterating over all the elements of a
collection. However, often the first or last element of the collection must
be handled differently than the others in the collection. For example, if
we were generating a list of items for display, we'd want a comma after
every item except the last. In these cases, foreach cannot be used, and the
alternates which can be used are generally ugly and often less efficient
than foreach. An elegant solution keeping with the concept of C# is needed.

The proposal:
I suggest adding four new keywords (only available inside foreach block) to
direct the compiler to our exact intentions. "first:" "last:" "other:"
"all:"

Example:
foreach (Person p in personCollection)
{
first:
Console.WriteLine("Names: {0},", p.Name");
other:
Console.WriteLine(" {0},", p.Name");
last:
Console.WriteLine(" {0}", p.Name");
}
A block not preceeded by one of those keywords would be assumed to be an
"all:" block, exact as is the case now.

Analysis:
The advantages of the feature:
It solves a problem in an elegant way, keeping with the design concepts of
C#.
It is handled entirely by the compiler, so that it has ZERO effect on code
that does not use it, and it requires no changes to the class framework or
the CLR. (These were problems with other suggested solutions for this)

The disadvantages:
It requires four keywords, although this could be reduced to three
(eliminating "all:") and, they would each be very context sensitive, so the
conflicts with user-defined identifiers is unlikely.

Implementation:
Presently, a foreach construct is largely "syntactic sugar" around a while
loop using an IEnumerator, such that code written as
foreach (int i in arry)
{
Console.WriteLine(i);
}

Would be compiled much as if it were written:
IEnumerator n = arry.GetEnumerator();
while(n.MoveNext())
{
int i = (int) n.Current;
Console.WriteLine(i);
}

Similarly, code using these blocks would also have a direct translation:
foreach (int i in arry)
{
First:
Console.WriteLine("{0} - first", i);
Others:
Console.WriteLine(i);
}

Would be compiled as:
IEnumerator n = arry.GetEnumerator();
if (n.MoveNext())
{
int i = (int) n.Current;
Console.WriteLine("{0}-- first ", i);
while(n.MoveNext())
{
i = (int) n.Current;
Console.WriteLine(i);
}
}
(The internal representation of a "last:" block is a bit more involved, but
still basically straightforward)

Any comments are suggestion would be appreciated.

Truth,
James Curran
MVP (for .um. VC++)

Paul E Collins

unread,
Apr 4, 2004, 8:37:57 AM4/4/04
to
"James Curran" <James...@mvps.org> wrote:

> [...]


> The foreach statement allows iterating over all the
> elements of a collection. However, often the first
> or last element of the collection must be handled
> differently than the others in the collection.

> [...]


> Presently, a foreach construct is largely "syntactic
> sugar" around a while loop using an IEnumerator

> [...]

I'd say that your proposal is rather unpleasant-looking "syntactic sugar" in
itself.

'foreach' and indexed 'for' are pretty much interchangeable. Using a 'for'
loop in those special cases and checking for specific iterations is hardly a
cumbersome task, certainly not enough so to merit a new keyword in the
language. What if it's the *second* iteration you want to treat differently;
should there be a 'second' keyword as well, or some kind of 'foreach ...
case' construct?

> Any comments are suggestion would be appreciated.

I just don't think it's necessary.

I'm somewhat influenced by the fact that I tend to use 'foreach' when I want
to iterate over all of the elements but don't care which order they come up
in. When I want things in a definite order, I use 'for'. (Is IEnumerator
supposed to return things in any particular order? I don't know.)

P.


James Curran

unread,
Apr 4, 2004, 11:17:46 AM4/4/04
to

"Paul E Collins" <find_my_re...@CL4.org> wrote in message
news:c4ovj5$ij8$1...@hercules.btinternet.com...

> 'foreach' and indexed 'for' are pretty much interchangeable.

Actually they aren't. foreach works for every class that implements
IEnumerable, which is small and easy to implement. Indexing requires
implementing IList which is more complicated. Many collection
implementations don't lend themselves well to indexing (anything which using
a tree instead of an array behind the scenes). Check out their desciption
pages in the MSDN. In the framework over twice as many classes implement
IEnumerable as IList.

>> I'm somewhat influenced by the fact that I tend to use 'foreach' when I
want
to iterate over all of the elements but don't care which order they come up
in <<

Just because there is no particular order to the items in the collection,
does not mean when being processed, the first and last do not need to be
processed differently. As in my example of adding the comma, often it's just
the fact that this item is the first processed is enough to require special
processing.

>What if it's the *second* iteration you want to treat differently;
> should there be a 'second' keyword as well, or some kind of 'foreach ...
> case' construct?

No. Needing to treat the first or last item differently is fairly common.
Needing to treat an item besides the first or last differently is much
rarer. Also, there is no simple implementation for treating a middle item
differently.

I guess the basic question is what is the point of having a foreach in the
language anyway, when it can always be replaced by a for or while statement?
If you see an advantage in having it in the language, you should see the
advantage of this.


Daniel O'Connell [C# MVP]

unread,
Apr 4, 2004, 12:39:25 PM4/4/04
to

"James Curran" <James...@mvps.org> wrote in message
news:OE9znajG...@TK2MSFTNGP12.phx.gbl...

> I'd like to make the following proposal for a new feature for the C#
> language. I have no connection with the C# team at Microsoft. I'm
> posting
> it here to gather input to refine it, in an "open Source" manner, and in
> an
> attempt to build a ground-swell of support to convince the folks at
> Microsoft to add it.
> Proposal: "first:" "last:" sections in a "foreach" block
>
> The problem:
> The foreach statement allows iterating over all the elements of a
> collection. However, often the first or last element of the collection
> must
> be handled differently than the others in the collection. For example, if
> we were generating a list of items for display, we'd want a comma after
> every item except the last. In these cases, foreach cannot be used, and
> the
> alternates which can be used are generally ugly and often less efficient
> than foreach. An elegant solution keeping with the concept of C# is
> needed.
>

Ok, I agree that this is a situation where no elegant solution exists. I've
seen a few other solutions that would help with this(implicit index and
length variables, my own named enumerators with an extended IEnumerator) but
as you illustrate they aren't easy or possible without modifying base
classes..


> The proposal:
> I suggest adding four new keywords (only available inside foreach block)
> to
> direct the compiler to our exact intentions. "first:" "last:" "other:"
> "all:"
>

While this is interesting, I have to agree with Paul that it doesn't catch
edge cases, which is something that needs to be addressed. I'll continue to
think about it and see what I can think of to manage such. There is
potential utility in this(although it may not be a feature that would make
the mainstream compiler) and it is atleast worth exploring.

> The disadvantages:
> It requires four keywords, although this could be reduced to three
> (eliminating "all:") and, they would each be very context sensitive, so
> the
> conflicts with user-defined identifiers is unlikely.

all could either be implicit and\or you could piggy back with default.
Additionally using case <label>:(or another word) and treating a foreach
like a switch would allow you to modify the syntax without disrupting
existing code. Two word keywords are syntactically possible(as evidenced
with yield in C# 2.0) while it isn't legal to have a two word identifier.

I think that for features like this the best way to explore the usage is to
actually use them. Have you considered modifying mono or rotor and adding
the feature(or permutations of it)? It will give you, and others if you
release it, a chance to see how it would really work in real code.

Daniel O'Connell [C# MVP]

unread,
Apr 4, 2004, 12:39:50 PM4/4/04
to

"Paul E Collins" <find_my_re...@CL4.org> wrote in message
news:c4ovj5$ij8$1...@hercules.btinternet.com...
> "James Curran" <James...@mvps.org> wrote:
>
>> [...]
>> The foreach statement allows iterating over all the
>> elements of a collection. However, often the first
>> or last element of the collection must be handled
>> differently than the others in the collection.
>> [...]
>> Presently, a foreach construct is largely "syntactic
>> sugar" around a while loop using an IEnumerator
>> [...]
>
> I'd say that your proposal is rather unpleasant-looking "syntactic sugar"
> in
> itself.
>
> 'foreach' and indexed 'for' are pretty much interchangeable. Using a 'for'
> loop in those special cases and checking for specific iterations is hardly
> a
> cumbersome task, certainly not enough so to merit a new keyword in the
> language. What if it's the *second* iteration you want to treat
> differently;
> should there be a 'second' keyword as well, or some kind of 'foreach ...
> case' construct?

I prefer case or another context sensitive keyword myself. case first;case
last;case index 2; case index 5;case index default;case all may work and
wouldn't cause existing code to fail.


>
>> Any comments are suggestion would be appreciated.
>
> I just don't think it's necessary.
>
> I'm somewhat influenced by the fact that I tend to use 'foreach' when I
> want
> to iterate over all of the elements but don't care which order they come
> up
> in. When I want things in a definite order, I use 'for'. (Is IEnumerator
> supposed to return things in any particular order? I don't know.)

Not defined by any standard, atleast globablly. An enumerator returns
objects in whatever order it sees fit. A given implementation of an
IEnumerator can specify that it returns objects that are sorted, or the
order they are stored in the IList, or reversed or what not, but there is no
explicit standard.
>
> P.
>
>


cody

unread,
Apr 4, 2004, 12:47:32 PM4/4/04
to
> The foreach statement allows iterating over all the elements of a
> collection. However, often the first or last element of the collection
must
> be handled differently than the others in the collection. For example, if
> we were generating a list of items for display, we'd want a comma after
> every item except the last. In these cases, foreach cannot be used, and
the
> alternates which can be used are generally ugly and often less efficient
> than foreach.

In that case, you should use the Enumerator directly with a for loop which
gives you full control over the enumeration.

e.MoveNext();
DosomethingWithFirstElement(e.Current);

while(e.MoveNext())
{
Object o = e.Current;
}

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk


C# Learner

unread,
Apr 4, 2004, 1:00:42 PM4/4/04
to
James Curran wrote:

> I'd like to make the following proposal for a new feature for the C#
> language. I have no connection with the C# team at Microsoft. I'm posting
> it here to gather input to refine it, in an "open Source" manner, and in an
> attempt to build a ground-swell of support to convince the folks at
> Microsoft to add it.
> Proposal: "first:" "last:" sections in a "foreach" block
>

> [...]

This isn't a bad idea at all, in my opinion. As you say, one must
appreciate 'foreach' to appreciate this idea.

I've got a feeling that people in general might prefer something like
the following, though:

Jon Skeet [C# MVP]

unread,
Apr 4, 2004, 1:10:59 PM4/4/04
to
Paul E Collins <find_my_re...@CL4.org> wrote:

<snip - I'm still mulling over the suggestion itself>

> I'm somewhat influenced by the fact that I tend to use 'foreach' when I want
> to iterate over all of the elements but don't care which order they come up
> in. When I want things in a definite order, I use 'for'. (Is IEnumerator
> supposed to return things in any particular order? I don't know.)

IEnumerator's GetEnumerator method specifies:

<quote>
Enumerators only allow reading the data in the collection.
...
Initially, the enumerator is positioned before the first element in the
collection.
...
Current returns the same object until either MoveNext or Reset is
called. MoveNext sets Current to the next element.
</quote>

That would suggest to me that if the collection *has* a natural order,
the enumerator should return elements in that order. I certainly have
no compunction with relying on foreach to iterate through an IList in
the natural way.

It's when the collection *doesn't* have an obvious natural order (e.g.
for Hashtables) that I wouldn't want to rely on the ordering.

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Daniel O'Connell [C# MVP]

unread,
Apr 4, 2004, 2:19:14 PM4/4/04
to

"Jon Skeet [C# MVP]" <sk...@pobox.com> wrote in message
news:MPG.1ada5200e...@msnews.microsoft.com...

> Paul E Collins <find_my_re...@CL4.org> wrote:
>
> <snip - I'm still mulling over the suggestion itself>
>
>> I'm somewhat influenced by the fact that I tend to use 'foreach' when I
>> want
>> to iterate over all of the elements but don't care which order they come
>> up
>> in. When I want things in a definite order, I use 'for'. (Is IEnumerator
>> supposed to return things in any particular order? I don't know.)
>
> IEnumerator's GetEnumerator method specifies:
>
> <quote>
> Enumerators only allow reading the data in the collection.
> ...
> Initially, the enumerator is positioned before the first element in the
> collection.
> ...
> Current returns the same object until either MoveNext or Reset is
> called. MoveNext sets Current to the next element.
> </quote>
>

Thats IEnumerable actually. While IEnumerator has the same suggestion, I
think its a touch irresponsible to define an IEnumerator as working in any
order. The semantics of IEnumerable, espeically when working with IList,
suggest to me that natural order should be used when available and no
documentation says otherwise, but a given IEnumerator should not be
constrained in its design by any specification(Although that is pretty moot
considering foreach can't handle IEnumerator directly, unfortunatly).

Its picky, I know, but I consider the difference between the two an
important point that MSDN and C# to an extent doesn't really illustrate
well.

Julie

unread,
Apr 4, 2004, 3:24:17 PM4/4/04
to
James Curran wrote:
> The problem:
> The foreach statement allows iterating over all the elements of a
> collection. However, often the first or last element of the collection must
> be handled differently than the others in the collection. For example, if
> we were generating a list of items for display, we'd want a comma after
> every item except the last. In these cases, foreach cannot be used, and the
> alternates which can be used are generally ugly and often less efficient
> than foreach. An elegant solution keeping with the concept of C# is needed.

I don't disagree that there could be some potential benefit.

However, in the case that you state, it is relatively simple to handle this
case:

String output = "Names: ";
foreach (String name in names)
{
output += name + ",";
}
output.TrimEnd(",");
Console.WriteLine(output);

Which in my opinion is pretty readable.

I think that the biggest problem is the last: case. During enumeration, the
last element isn't determinable until you are past the end, and therefore would
impose more requirements on collections.

James Curran

unread,
Apr 4, 2004, 3:30:30 PM4/4/04
to
"C# Learner" <csh...@learner.here> wrote in message
news:%23qJmnZm...@TK2MSFTNGP09.phx.gbl...

> I've got a feeling that people in general might prefer something like
> the following, though:
>
> foreach (Person p in personCollection)
> {
> first
> {
> Console.WriteLine("Names: {0},", p.Name");
> }
> other
[snip]
> }

Actually, as I originally planned the original post, I had intended a
section for "possible alternate syntaxes" which included that as well as
Daniel's "case" syntax. Unfortunately, as I was writing at 4AM, some parts
had to be pared out in the hopes of getting some sleep. But I'm not married
to any particular syntax, and open to all suggestions.

Truth,
James Curran


James Curran

unread,
Apr 4, 2004, 3:41:35 PM4/4/04
to
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:%23Rk5xNm...@TK2MSFTNGP10.phx.gbl...

> I prefer case or another context sensitive keyword myself. case first;case
> last;case index 2; case index 5;case index default;case all may work and
> wouldn't cause existing code to fail.

The use of "case first" et al was to be in a section of "alternate syntaxes"
which got inadvertantly dropped from the original post.

However "case index 2:" poses problems because presently the IEnumerator
doesn't store the index value, whidch means to implement it, we'd have to
increase the size of every IEnumerator object (to store the index), and
increase the work done by IEnumerator.MoveNext (to update the index), which,
well, breaks everything currently using IEnumerator. This very issue was
dealt with by Raymond Chen of MSFT in this blog
http://dotnetjunkies.com/WebLog/d0m1/archive/2004/01/28/6199.aspx#FeedBack.
I should note that this proposal grew out of that Blog entry by Dominic
Morris, which attracted comments from several MSFT employee, and was written
in light of their comments.

Truth,
James Curran


Jon Skeet [C# MVP]

unread,
Apr 4, 2004, 4:09:29 PM4/4/04
to
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote:
> Thats IEnumerable actually.

Oops, yes.

> While IEnumerator has the same suggestion, I
> think its a touch irresponsible to define an IEnumerator as working in any
> order. The semantics of IEnumerable, espeically when working with IList,
> suggest to me that natural order should be used when available and no
> documentation says otherwise, but a given IEnumerator should not be
> constrained in its design by any specification(Although that is pretty moot
> considering foreach can't handle IEnumerator directly, unfortunatly).

I would agree that it's not really the place of IEnumerable/IEnumerator
to define the order. IList.GetEnumerator should do it, in my view - the
MSDN is unfortunate in not tending to define the meaning of overridden
methods in the overriding classes any more than the base
class/interface does :(

> Its picky, I know, but I consider the difference between the two an
> important point that MSDN and C# to an extent doesn't really illustrate
> well.

Sure - and well spotted.

Daniel O'Connell [C# MVP]

unread,
Apr 4, 2004, 4:20:03 PM4/4/04
to

"James Curran" <James...@mvps.org> wrote in message
news:%23LqFbzn...@TK2MSFTNGP12.phx.gbl...

> "Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
> message news:%23Rk5xNm...@TK2MSFTNGP10.phx.gbl...
>> I prefer case or another context sensitive keyword myself. case
>> first;case
>> last;case index 2; case index 5;case index default;case all may work and
>> wouldn't cause existing code to fail.
>
> The use of "case first" et al was to be in a section of "alternate
> syntaxes"
> which got inadvertantly dropped from the original post.

Syntax is always the hard part. I think I like case <lable> more than I like
the foreach.first syntax suggested in that post.


>
> However "case index 2:" poses problems because presently the IEnumerator
> doesn't store the index value, whidch means to implement it, we'd have to
> increase the size of every IEnumerator object (to store the index), and
> increase the work done by IEnumerator.MoveNext (to update the index),
> which,
> well, breaks everything currently using IEnumerator. This very issue was
> dealt with by Raymond Chen of MSFT in this blog
> http://dotnetjunkies.com/WebLog/d0m1/archive/2004/01/28/6199.aspx#FeedBack.
> I should note that this proposal grew out of that Blog entry by Dominic
> Morris, which attracted comments from several MSFT employee, and was
> written
> in light of their comments.
>

I don't think it would need to be done by modifying IEnumerator. Like Eric
Gunnerson points out,

int index = 0;
foreach (string s in list)
{
if (index++ == 0)
{
// do something special here
}
}

would do it. Instead of producing an explicit variable, I would instead let
the compiler generate a temporary and use the case index X syntax to match
against that value. Ideally the compiler would only generate the temp and
bother with that *if* a case index existed within the foreach block. I would
argue against the need for an index available in the foreach as a feature on
its own, but support like you suggest here would be reason enough to
logically extend the system to provide index casing.
> Truth,
> James Curran
>
>


Daniel O'Connell [C# MVP]

unread,
Apr 4, 2004, 4:39:18 PM4/4/04
to

"Julie" <ju...@nospam.com> wrote in message
news:407060E0...@nospam.com...

It is harder to do but not impossible. Consider

foreach (char x in "Mouse")
{
case first: Console.WriteLine("First: " + x);
case last: Console.WriteLine("Last: " + x);
case other: Console.WriteLine("Middle: " + x);

}

The compiler could translate it into something like:

IEnumerator enumerator = ((IEnumerable)"Mouse").GetEnumerator();
enumerator.MoveNext();
//first
char x = (char)enumerator.Current;
Console.WriteLine("First: " + x);
//end first
if (enumerator.MoveNext())
{
while (true)
{
x = (char)enumerator.Current;
//other
if (enumerator.MoveNext() == false)
break;
Console.WriteLine("Middle: " + x);
//end other
}
//last
Console.WriteLine("Last: " + x);
}

which results in

First: M

Middle: o

Middle: u

Middle: s

Last: e

The real question is where does "all" fit in. Should it exectue before or
after a given case?


Jeffrey Tan[MSFT]

unread,
Apr 5, 2004, 5:29:34 AM4/5/04
to
Hi James,

Thanks very much for your suggestion.

I have viewed it, and I think it really makes sense. I suggest you provide
your suggestion to:
http://register.microsoft.com/mswish/suggestion.asp

Also, I will forward your suggestion to our product group. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Dilip Krishnan

unread,
Apr 5, 2004, 11:02:56 AM4/5/04
to
I would think that by the definition of foreach, the language construct
is unable to predict the size of the enumerable in question. Which would
mean that the foreach loop would need to read-ahead to determine the
ordinality of the enumerable list. IMHO that would make the whole
foreach inefficient would'nt you say?

James Curran wrote:

--
Regards,
Dilip Krishnan
MCAD, MCSD.net
dilipdotnet at apdiya dot com

Jon Skeet [C# MVP]

unread,
Apr 5, 2004, 3:09:31 PM4/5/04
to
Dilip Krishnan <dilipdotnet..NOSPAM..@apdiya.com> wrote:
> I would think that by the definition of foreach, the language construct
> is unable to predict the size of the enumerable in question. Which would
> mean that the foreach loop would need to read-ahead to determine the
> ordinality of the enumerable list. IMHO that would make the whole
> foreach inefficient would'nt you say?

You don't need to know the ordinality though - you only need to know
first or last. First is obvious, and the "last" bit you just execute
when the next MoveNext returns false (or whatever - I can't remember
the exact interface offhand). It would be slightly trickier to make the
"last" case not also execute "other", and it would be easier to
basically make that something executed *as well as* the "other" case,
but other than that it's not tricky.

Joep

unread,
Apr 5, 2004, 6:06:21 PM4/5/04
to
IMHO

foreach means foreach means foreach, so for each item of a collection of
items do this. I would not like to see a switch inside the loop that test
for the first or the last or whichever item. It conflicts with what I
learned long time ago about loop-unrolling and its effect.

Instead, I would like to state foreach item in this (not that) collection do
this, this collection excluding the first and last item for example, in
other words, I would like to be able to more precisely define the items for
which I want some code to execute. It could be that I want to execute this
for every other item and that for all the others.

What about something along these lines where I would be able to define a
part of the collection of items? A bit like string.substring and similar
constructs.

foreach(item in items[2,8])

or

foreach(item in items[2,])

or like the Python splice thingy?

The suggestion I like, meaning a way to more precisely define which items to
execute code for. Syntax and semantics are another thing.

Can't this be done already I wonder...

Daniel O'Connell [C# MVP]

unread,
Apr 5, 2004, 7:17:19 PM4/5/04
to

"Joep" <St...@DeStoep.nl> wrote in message
news:4071d714$0$559$e4fe...@news.xs4all.nl...

> IMHO
>
> foreach means foreach means foreach, so for each item of a collection of
> items do this. I would not like to see a switch inside the loop that test
> for the first or the last or whichever item. It conflicts with what I
> learned long time ago about loop-unrolling and its effect.
>
> Instead, I would like to state foreach item in this (not that) collection
> do
> this, this collection excluding the first and last item for example, in
> other words, I would like to be able to more precisely define the items
> for
> which I want some code to execute. It could be that I want to execute this
> for every other item and that for all the others.
>
> What about something along these lines where I would be able to define a
> part of the collection of items? A bit like string.substring and similar
> constructs.
>
> foreach(item in items[2,8])
>
> or
>
> foreach(item in items[2,])
>
> or like the Python splice thingy?

A few problems with this.

Order returned by an enumerator is only statically defined during the
lifetime of the enumerator. There is nothing that requires two sequential
executions of foreach over the same object to actually process the items in
the same order(or really that IEnumerator isn't strictly required to
maintain predictable order). In some situations, say when used with IList, a
natural order can be established, but in other cases when you are
considering a tree or a hashtable or an enumerator that generates its
results there may not be a natural order and ordering *may* be
unpredictable. In which case it wouldn't be possible to achieve the original
point of the feature propsal.

Another is that, unless you happen to know the length of the enumerator,
this syntax doesn't help you in the least with determining when the last
item occurs. Again, in data structures its probable that you'll get a count,
but its certainly not definate.

Yet another, somewhat related to the above, is that foreach (x in
enumerator[1]) isn't particularly sensible but it would have to be done
unless you wanted to directly access the enumerator. Also when you consider
index 0 may not be the first value returned by the IEnumerator you can't
even rely on an indexer in all cases(assuming one even exists).


>
> The suggestion I like, meaning a way to more precisely define which items
> to
> execute code for. Syntax and semantics are another thing.

This suggestion is interesting, but it simply isn't the same as the original
proposal. This particular syntax allows you to specify a range to exectue
over while the original proposed a way to execute code based entirely on the
order in the enumeration, not the list or whatever the values are being read
from. The syntax proposed could operate with what you proposed pretty simply

foreach (char x in str[1,4])
{
case first: Console.WriteLine("First: " + x); //matches the first value,
in this case str[1]
case last: Console.WriteLine("Last: " + x); //matchs the last value, in
this case str[4]
case other: Console.WriteLine("Middle: " + x); //matches all cases other
than str[4] and str[5]

}

Of course, new syntax needs to exist. The indexer accessor would be
conflicting with actual indexers(Imagine an indexer that returns an
IEumerable).


>
> Can't this be done already I wonder...

In theory you could do it with a custom IEnumerable\IEnumerator pair that
wraps an existing IEnumerator, but there is no syntax I nkow of.


James Curran

unread,
Apr 6, 2004, 8:55:14 PM4/6/04
to
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:O50hlNmG...@TK2MSFTNGP12.phx.gbl...

> I think that for features like this the best way to explore the usage is
to
> actually use them. Have you considered modifying mono or rotor and adding
> the feature(or permutations of it)? It will give you, and others if you
> release it, a chance to see how it would really work in real code.

Actually, it had never occured to my the source to a C# compiler would
be available. Though I'm not sure if I want to attempt adding features to
one. (But I have now downloaded the mono source, and will be looking into
it)


Daniel O'Connell [C# MVP]

unread,
Apr 7, 2004, 12:16:21 AM4/7/04
to

"James Curran" <James...@mvps.org> wrote in message
news:uqKWDsDH...@TK2MSFTNGP10.phx.gbl...
LOL, ya, there is atleast mono's compiler(there is a compiler in rotor as
well, but its in C++(although you're probably better equiped to deal with it
than I) written in C#. I have done some fair amount of modification to the
mcs compiler(bout a half dozen experimental features), so I might be able to
help if you have any problems.
>
>


SpookyET

unread,
Apr 10, 2004, 1:10:11 PM4/10/04
to
This makes no sense, if you want access to the indexer, use a for loop.
foreach loops are 50% slower than for loops anyway, which means that you
should use them in very few cases.

Tim Jarvis

unread,
Apr 10, 2004, 1:17:17 PM4/10/04
to
SpookyET wrote:

50%

That's a very specific number...where did you get that info from ?

Rgds Tim.

Jon Skeet [C# MVP]

unread,
Apr 10, 2004, 1:40:25 PM4/10/04
to

And in what context? Depending on the type you're indexing, foreach can
be faster than using an indexer.

SpookyET

unread,
Apr 10, 2004, 2:53:06 PM4/10/04
to
It isn't a real number. There is this episode of the .NET Show called
Code Optimizations at
http://msdn.microsoft.com/theshow/Episode027/default.asp where it shows
you on how to optimize your code. A for loop took 1sec, forceach 1.5
secs, 2 secs. You can test it yourself by downloading the code and
playing with it. The fact is that foreach is way slower and it makes
sense to be slower. Take a look at the code behind forceach at
http://www.jaggersoft.com/csharp_standard/15.8.4.htm and see for yourself!

On Sat, 10 Apr 2004 10:17:17 -0700, Tim Jarvis <tja...@NoSpamForMe.com>
wrote:

cody

unread,
Apr 10, 2004, 3:39:18 PM4/10/04
to
> It isn't a real number. There is this episode of the .NET Show called
> Code Optimizations at
> http://msdn.microsoft.com/theshow/Episode027/default.asp where it shows
> you on how to optimize your code. A for loop took 1sec, forceach 1.5
> secs, 2 secs. You can test it yourself by downloading the code and
> playing with it. The fact is that foreach is way slower and it makes
> sense to be slower. Take a look at the code behind forceach at
> http://www.jaggersoft.com/csharp_standard/15.8.4.htm and see for yourself!


This is not always true. for example with arrays a for loop should perform
with
the same speed as foreach since here are no Enumerators involved.

Daniel O'Connell [C# MVP]

unread,
Apr 10, 2004, 4:13:59 PM4/10/04
to

"cody" <please_dont.s...@gmx.de> wrote in message
news:%23eOK5Pz...@tk2msftngp13.phx.gbl...

>> It isn't a real number. There is this episode of the .NET Show called
>> Code Optimizations at
>> http://msdn.microsoft.com/theshow/Episode027/default.asp where it shows
>> you on how to optimize your code. A for loop took 1sec, forceach 1.5
>> secs, 2 secs. You can test it yourself by downloading the code and
>> playing with it. The fact is that foreach is way slower and it makes
>> sense to be slower. Take a look at the code behind forceach at
>> http://www.jaggersoft.com/csharp_standard/15.8.4.htm and see for
>> yourself!
>
>
> This is not always true. for example with arrays a for loop should perform
> with
> the same speed as foreach since here are no Enumerators involved.
Also, though I can't remember which structures specifically, there are cases
where foreach will result in better performance than for. Things like linked
lists, trees, etc may be faster via a foreach since its possible for the
foreach to be written so that it doesn't have to iterate the collection
every time. An indexer would.

Tim Jarvis

unread,
Apr 10, 2004, 5:00:16 PM4/10/04
to
SpookyET wrote:

> It isn't a real number. There is this episode of the .NET Show
> called Code Optimizations at
> http://msdn.microsoft.com/theshow/Episode027/default.asp where it
> shows you on how to optimize your code. A for loop took 1sec,

The problem with this type of benchmark in a demo is this, the point
that they are trying to make is that you need to look at specific areas
to tune your code, and they are giving a for instance...

Our product managers and technical sales guys do the same kind of thing
when they are demo'ing Optimise it (I work for Borland) and they will
show some code that needs to be optimised, the biggest impact is when
they show reasonable looking code that performs poorly. It is usually a
pretty bogus piece of code to be honest, but that is not the point of
the demo, the demo is to show how the poorly performing code can be
found.

I would not dispute that a foreach performs worse in some situations
than other loop types, and I would agree that if you are code tuning
that this is an area to look at, perhaps using a monitoring tool would
be another course of action ;-) But I would not be so bold as to quote
percentage figures, especially from a demo, that is specifically
designed around tuning code, that's just asking for dispute.

IMO when tuning code, sometimes a piece of code that performs
adequately, but is very clear in it's intent is better to have in your
source than highly performing, but slightly less obvious code, I think
that too many people leave the time taken in trying to understand old
code out of the equation when code tuning.

Please don't take this to mean that I don't advocate tuning code
(including foreach's) because that is *not* the case, but I think that
some sense needs to be applied and not based upon a MS demo in a code
tuning tutorial, the critera needs to be based upon the requirements of
the application balanced against the requirements of maintenance.

Rgds Tim.

Tim Jarvis

unread,
Apr 10, 2004, 5:28:36 PM4/10/04
to
Daniel O'Connell [C# MVP] wrote:

> treating a foreach like a switch would allow you to modify the syntax
> without disrupting existing code. Two word keywords are syntactically

For me this would be the key thing, I would hope the obvious thing as
well ;-)

Rgds Tim.

cody

unread,
Apr 10, 2004, 5:57:32 PM4/10/04
to
> > This is not always true. for example with arrays a for loop should
perform
> > with
> > the same speed as foreach since here are no Enumerators involved.
> Also, though I can't remember which structures specifically, there are
cases
> where foreach will result in better performance than for. Things like
linked
> lists, trees, etc may be faster via a foreach since its possible for the
> foreach to be written so that it doesn't have to iterate the collection
> every time. An indexer would.


Additionally, the jitter removes the range-check when enumerating over an
array or a string or a StringBuffer.

James Curran

unread,
Apr 15, 2004, 5:57:38 PM4/15/04
to
"SpookyET" <not...@hotmail.com> wrote in message
news:opr5872sz91s9n15@saturn...

> It isn't a real number. There is this episode of the .NET Show called
> Code Optimizations at
> http://msdn.microsoft.com/theshow/Episode027/default.asp where it shows
> you on how to optimize your code. A for loop took 1sec, forceach 1.5
> secs, 2 secs. You can test it yourself by downloading the code and
> playing with it.

Try changing the type of the collection. With an ArrayList, for() wins.
But with a Hashtable, foreach() wins by 3X to 4X.

Or better yet... Try changing the collection to a BitArray or a Cache
(or a Queue or a Stack or a StateBag or an XmlNodeList) --- BUT you can't!
You can't index any of those! (But you can use foreach on them)


--
Truth,
James Curran
Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
(note new day job!)


cody

unread,
Apr 16, 2004, 12:42:16 PM4/16/04
to
> Or better yet... Try changing the collection to a BitArray or a Cache
> (or a Queue or a Stack or a StateBag or an XmlNodeList) --- BUT you can't!
> You can't index any of those! (But you can use foreach on them)


you CAN index a BitArray.

0 new messages