473,399 Members | 3,919 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,399 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 2792
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: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.