473,231 Members | 2,698 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,231 software developers and data experts.

for vs foreach for array enumeration

I'm a bit confused about the differences of these two commands (what is
the right word for commands here?) when used to enumerate the contents
of an array.

The below example uses both foreach and for to enumerate the contents
of the array.
Also as well as explaining the differences could you explain why the
foreach messagebox isn't working below.

Many TIA.
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace array_examples
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
int[] intarray = new int[] { 5, 6, 7, 8 };
MessageBox.Show("This example uses for");
for (int i = 0; i < intarray.Length; i++)
{
MessageBox.Show(intarray[i].ToString());
}
MessageBox.Show("While this example uses foreach");
foreach (int y in intarray)
{
MessageBox.Show(intarray[y].ToString());
}

}
}
}

Nov 29 '06 #1
9 2784
foreach uses the specific enumerator provided by the class in question (in
this case an array) via the GetEnumerator() method (usually exposed via an
IEnumerable implementation), and on successive loops returns the actual item
(not the index) at that location; so your code should read:
MessageBox.Show(y.ToString());

This adds a little overhead in terms of an enumerator object etc, so
*technically* for very simple items like arrays the indexer performance is
slightly faster. However, in general having to tell the caller what your
implementation (array, collection, list) is a headache, so code tends to be
more reusable using foreach (and IEnumerable).

Additionally, you should generally assume that the provided enumerator is an
appropriate implementation - for instance, in a linked list an enumerator
would simply walk the chain as you "next", but "for" usage using the indexer
(myList[i] etc) could be catastrophic, as it would telescope the effort
(O(n^2) instead of O(n) for enumerator access).

In 2.0 you also have IEnumerable<Twhich adds strong typing to the mix.

The other advantage of IEnumerable is that you can use it in cases where
*you don't know how long the list is*. For instance, I could knock together
an IEnumerable wrapper for random data, or a series like Fibonacci, etc - or
(more typically) for lazy reading data where you simply can't tell the size
until it is complete. 2.0 also adds "yield return" to simplify writing
enumerators.

Marc
Nov 29 '06 #2
Marc Gravell schrieb:
[..]

Marc

Additionally, while using the foreach loop, you cannot add or remove
items from the array, list, whatever. With fo you can, but be aware that
the indexes change. E.g. you process a list of objects and want to
remove all successfully processed objects. With a foreach loop this is
more difficult. With a for loop you loop back to front (to avoid index
impacts) like

for (int idx; idx = list.Count; --idx;) { // do stuff }

Furthermore the for loop allows you to start and end at any index in the
list or specify any breaking conditions for the loop.

Tobi

Btw.: IMHO, "(control) statement" would be the appropriate word instead
of "command" here.
Nov 29 '06 #3
Thankyou both very much i've learnt a great deal there.

This is new ground for me. Would someone please mind answering the
following questions that your answers have made me wonder.

1. What is IEnumerable
i've seen this before but don't understand what it is / what it does.

2. What is an enumerator object?

3. What does this mean?
I would like to understand it, but need it explained in as much detail
as possible please.

" for instance, in a linked list an enumerator
would simply walk the chain as you "next", but "for" usage using the
indexer
(myList[i] etc) could be catastrophic, as it would telescope the effort

(O(n^2) instead of O(n) for enumerator access). "

4. What is yield return?

5. What's the difference between a 'control statement' and a statement.
TIA Gary

Nov 29 '06 #4
OK...

IEnumerable is a very simple interface that means "I have contents that you
can query in a sequence"; it does this by a single method: GetEnumerator()
which returns an "enumerator".

An enumerator is an object that implements the IEnumerator interface; this
basically acts as a marker in a sequence, and has the following:
MoveNext() - move forward to the next item in the sequence (returns false if
at the end)
Reset() - go back to the start of the sequence (actually to *before* the
first item; MoveNext() must then be called to get to the first item)
Current - obtains the current item from the list.

Essentially, then, this is all a shortcut:
foreach(int y in array) {
// do something with y
}
really just means:
{
IEnumerator enumerator = array.GetEnumerator();
while(enumerator.MoveNext()) {
int y = (int) enumerator.Current
// do something with y
}
// dispose if disposable
IDisposable disposeMe = enumerator as IDisposable;
if(disposeMe!=null) disposeMe.Dispose();
}

Quite the short cut!
IEnumerable<Tand IEnumerator<Tare the same, but Current is typed as T
instead of object, so IEnumerable<intworks without casting and boxing.

*creating* an enumerator used to be a pain; for an array enumerator, this
would (I'd guess) just be a class with an integer representing the current
index that gets incremented by MoveNext(), and Current just returns the item
at the current index. But it is more complex for harder cases. To help with
this, in 2.0 you can get the compiler to do almost all of the work for you.
For instance, say I want an enumerator that combines two lists, and never
returns "null" values from the first list:

public IEnumerator GetEnumerator()
{
foreach (object item in list1)
{
if(item!=null)
yield return item;
}
foreach (object item in list2)
{
yield return item;
}
}

Job done. This code is invoked when the enumerator is initialised, and each
"yield return" corresponds to an item from MoveNext(). Note that through
some magic this method is interrupted - i.e. it does *NOT* run to completion
before the caller gets the data. The code runs to the first "yield return"
and then this value is returned to the caller via Current. When they
MoveNext() the code continues to the next "yield return" in the loop, etc,
until the method exists, which counts as the end of the data and thus
MoveNext() returns false and the method ends. Very, very sweet. It is
usually used with typed data and IEnumerator<Tetc, but the above works...

Marc
Nov 29 '06 #5
ga********@myway.com schrieb:
Thankyou both very much i've learnt a great deal there.

This is new ground for me. Would someone please mind answering the
following questions that your answers have made me wonder.

3. What does this mean?
I would like to understand it, but need it explained in as much detail
as possible please.

" for instance, in a linked list an enumerator
would simply walk the chain as you "next", but "for" usage using the
indexer
(myList[i] etc) could be catastrophic, as it would telescope the effort

(O(n^2) instead of O(n) for enumerator access). "
O(n) and O(n^2) refer to the execution time needed by an algorithm.
O(n) means, that execution time is lenear depenend on the number of
items to be prcessed. In a list example, this would be a simple foreach
loop (get each item in the list).
O(n^2) means, that execution time increased quadratically with the
number of items. For example, you loop the list items and for each item
you loop the list again:

foreach (item in list) {
foreach (innerItem in list) {
// do something
}
}

Generally the O-notation gives programmers an idea of how expensive an
algorithm is and allows comparsion of two algorithms that do the same
thing, just in different ways. A classical example might be sorting or
searching lists. Eg. Bubblesort with O(n^2) vs Mergesort with O(n*log(n)).
Search the web or wikipedia for more information on this topic, you
should find plenty :)
5. What's the difference between a 'control statement' and a statement.
Actually, I am not sure about the exact term. I'd use the above as
synonyms (in this context).
>

TIA Gary
1., 2. and 4. where answered by Marc already.

Tobi
Nov 29 '06 #6
Thankyou both very much.

It doesn't all make crystal clear sense, but I guess that will only
come with time.

I know ALOT more about this than when I began a couple of hours ago,
largely thanks to you both. So many, many thanks.

Gary.

Nov 29 '06 #7
Cheers - guess I missed #3, and I agree #5 is unclear.

Gary - to clarify why the indexer usage might be worse for a (hypothetical)
linked list, consider the following rough sketch implementation; the
GetEnumerator() (foreach) method walks the list *once* from end to end. The
indexer approach (for) would (for item i) go through i steps - and hence
would require n(n+1)/2 operations (IIRC), which means O(n^2) [we normally
only care about the higher powers of n]

Marc

private LinkItem GetByIndex(int index)
{
LinkItem item = First;
while (index 0) item = item.Next;
return item;
}
public T this[int index]
{
get { return GetByIndex(index).Value; }
set { GetByIndex(index).Value = value; }
}
public IEnumerator<TGetEnumerator()
{
LinkItem item = First;
while(item!=null) {
yield return item.Value;
item = item.Next;
}
}
Nov 29 '06 #8

ga********@myway.com wrote:
I'm a bit confused about the differences of these two commands (what is
the right word for commands here?)
I prefer construct or keyword. That's the terminology I use most often
anyway.

Nov 29 '06 #9
ga********@myway.com wrote:
foreach (int y in intarray)
{
MessageBox.Show(intarray[y].ToString());
}
Should just be
MessagBox.Show(y.ToString())

--
Lucian
Nov 29 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

104
by: cody | last post by:
What about an enhancement of foreach loops which allows a syntax like that: foeach(int i in 1..10) { } // forward foeach(int i in 99..2) { } // backwards foeach(char c in 'a'..'z') { } // chars...
32
by: Joe Rattz | last post by:
Hmmm, I wrote the following code. I want an array of bools and I want to intialize them to false. bool bits = new bool; foreach(bool bit in bits) { bit = false; } The compiler complains...
3
by: Filippo P. | last post by:
Hi there, I have a menu (Collection) that needs to be trimmed based on security access of the logged user. protected void AdjustMenuBasedOnUserSecurity(Items ItemsList) { foreach (Item i in...
5
by: David C | last post by:
This is very strange. Say I have code like this. I am simply looping through a collection object in a foreach loop. Course course = new Course(); foreach(Student s in course.Students) {...
25
by: David C | last post by:
I posted this question, and from the replies, I get the impression that I worded my posting very poorly, so let me try this again. While debugging and stepping through this foreach loop ...
13
by: hn.ft.pris | last post by:
Hi: I have the following simple program: #include<iostream> using namespace std; int main(int argc, char* argv){ const double L = 1.234; const int T = static_cast<const int>(L); int arr;
9
by: barcaroller | last post by:
Can variables be used for array size in C++? I know that in the past, I could not do the following: foo (int x) { type arr; } I have recently seen code that does exactly that. Is it right?
9
by: news.microsoft.com | last post by:
I am looping through an iteration and I would like to test the next item but if its not the one that I want how do I put it back so that when my foreach continues it is in the next iteration? ...
10
by: =?Utf-8?B?YmJn?= | last post by:
Hi all, I wanted to go through each entry(?) of ArrayList and remove some particular entry. So I tried following but it throws exception at runtime: foreach (myEntry entry in myArrayList) {...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.