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

IEnumerable objects are essentially arrays, right?

2 views
Skip to first unread message

gnewsgroup

unread,
May 11, 2008, 4:13:58 PM5/11/08
to
I've read the msdn doc about IEnumerable. It seems to me that
IEnumerable objects are essentially wrapped-up arrays. It simply gives
us the foreach convenience. Is this correct?

Jon Skeet [C# MVP]

unread,
May 11, 2008, 4:54:50 PM5/11/08
to

No, not at all.

IEnumerable represents a sequence of items - but unlike arrays:

1) It doesn't provide random access; you basically have to go forwards
(or start again)

2) It's read-only

3) IEnumerable is an *interface* - it can be implemented any way that's
appropriate

4) Arrays are always totally in-memory. IEnumerable implementations can
enumerate anything; for instance, it could enumerate each line in a web
response *as it arrives* without even knowing how long the response is.
Heck, you could enumerate an infinite random number sequence - it's up
to the caller to quit when they want to.

<blatant plug>
See http://www.manning-source.com/books/skeet/Chapter6sample.pdf for
rather more about the iterator pattern.
</blatant plug>

--
Jon Skeet - <sk...@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com

gnewsgroup

unread,
May 11, 2008, 5:27:07 PM5/11/08
to

Thank you. I know IEnumerable is an interface. I didn't mean
IEnumerable objects and arrays are exactly the same. I notice that
quite often the constructor of an IEnumerable class takes an array as
the argument, and I think foreach internally makes use of the MoveNext
method. Is it the case that the core of an IEnumerable object is an
array? Thanks.

Pavel Minaev

unread,
May 11, 2008, 5:44:17 PM5/11/08
to
On May 12, 1:27 am, gnewsgroup <gnewsgr...@gmail.com> wrote:

> Thank you. I know IEnumerable is an interface.  I didn't mean
> IEnumerable objects and arrays are exactly the same.  I notice that
> quite often the constructor of an IEnumerable class takes an array as
> the argument, and I think foreach internally makes use of the MoveNext
> method. Is it the case that the core of an IEnumerable object is an
> array? Thanks.

No, it is not. It all depends on which particular implementation of
IEnumerable you take. E.g. array itself is IEnumerable. List<T> is
IEnumerable and also wraps an array. But LinkedList<T> is IEnumerable,
and is not an array, nor does it behave like one (you can't access
elements by index). Another example would be method Enumerable.Range()
in .NET 3.5 - you give it a lower and an upper bound, and returns an
implementation of IEnumerable that produces numbers in that range. It
would be implemented something like this:

class Range : IEnumerable<int>
{
private int lowerBound, upperBound;

public Range(int lowerBound, int upperBound)
{
this.lowerBound = lowerBound;
this.upperBound = upperBound;
}

public IEnumerator<int> GetEnumerator()
{
for (int i = lowerBound; i <= upperBound; ++i)
{
yield return i;
}
}
}

As you can notice, there are no arrays here at all...

The concept that IEnumerable represents is actually a "sequence" (a
finite or an infinite one - noone says that MoveNext() ever has to
return false!). "Array" is a more specific concept - to quote
Wikipedia, "In computer science an array is a data structure
consisting of a group of elements that are accessed by indexing. In
most programming languages each element has the same data type and the
array occupies a contiguous area of storage.". Obviously, any array is
also a sequence, but not every sequence is an array or even array-like
(since not every sequence can be indexed, and some - e.g.
Dictionary<T> and HashSet<T> - do not even have any specific ordering).

gnewsgroup

unread,
May 11, 2008, 7:10:23 PM5/11/08
to

Thank you very much. I think it is much clearer to me. The range
example you gave is actually a question I have which I am planning on
following up in this thread, although really the example I am
interested in is the Power example as shown at
http://msdn.microsoft.com/en-us/library/9k7k7cf0(VS.80).aspx . You'll
notice that it is very similar to your Range example.

The question I have about the Power example is:

The while loop:

while (counter++ < exponent)
{
result = result * number;
yield return result;
}

indicates that block likely will execute multiple times. The question
is, where does the result go? Note that result is declared as an
int. Is it converting the int result to IEnumerable and pad the
result to this IEnumberabilized result? This is where I don't
understand. I hope that I have made my question clear. Thank you.

Tim Jarvis

unread,
May 11, 2008, 7:28:26 PM5/11/08
to
gnewsgroup wrote:

> > <blatant plug>
> > See http://www.manning-source.com/books/skeet/Chapter6sample.pdf for
> > rather more about the iterator pattern.

>

> Thank you. I know IEnumerable is an interface. I didn't mean
> IEnumerable objects and arrays are exactly the same. I notice that
> quite often the constructor of an IEnumerable class takes an array as
> the argument, and I think foreach internally makes use of the MoveNext
> method. Is it the case that the core of an IEnumerable object is an
> array? Thanks.

The thing about an Interface is that there is no requirement that the
underlying implementation is a specific class, thats the beauty of
interfaces they provide polymorphic behaviour /accross/ class
heirachy's. Its simply a contract that the underlying implementation
will provide a (in this case) GetEnumerator method, it so happens that
system.array does, but so do many other classes. So I guess the exact
answer to your question is Sometimes the "core" is an array, sometimes
its not.

Definitely have a read of Jon's chapter, he explains in quite some
detail what's going on.

Regards Tim.

--

Peter Duniho

unread,
May 11, 2008, 7:51:28 PM5/11/08
to
On Sun, 11 May 2008 16:10:23 -0700, gnewsgroup <gnews...@gmail.com>
wrote:

> [...]


> The question I have about the Power example is:
>
> The while loop:
>
> while (counter++ < exponent)
> {
> result = result * number;
> yield return result;
> }
>
> indicates that block likely will execute multiple times. The question
> is, where does the result go?

It's returned by IEnumerator.Current, where the IEnumerator is "returned"
(sort of) by the method in question, indirectly through the IEnumerable in
that particular example.

> Note that result is declared as an
> int. Is it converting the int result to IEnumerable and pad the
> result to this IEnumberabilized result? This is where I don't
> understand. I hope that I have made my question clear. Thank you.

To answer your direct question: no, the int is not converted to
IEnumerable.

It is a little confusing, because the compiler is hiding so much from
you. But a method that contains a "yield" statement is treated
differently from normal methods. The compiler essentially creates a
hidden class that implements the enumeration described by the method, via
the IEnumerable interface in this example.

This hidden class manages the current state. When you call the method,
all that's returned is a reference to the IEnumerable (or whatever type
was declared for the iterator) that the compiler created. Something using
IEnumerable (for example, a "foreach" loop) calls GetEnumerator() to get
the IEnumerator interface implemented by the hidden class. The compiler
has built the hidden class so that when you call IEnumerator.MoveNext(),
it executes the code in the method that you wrote until it hits the
"yield" statement. At that point, the return value is stored and the
MoveNext() implementation returns. Calling IEnumerator.Current retrieves
the stored value.

For the non-generic IEnumerable, the IEnumerator returned is of course a
non-generic implementation and so Current always returns an Object. When
the "yield" statement returns an int, this is boxed automatically. It's
then unboxed by whatever code is actually using the
IEnumerable/IEnumerator.

If you implement the generic IEnumerable<T> interface, then the value
returned by IEnumerator<T>.Current will be the same type as that returned
by the "yield" statement, without any boxing.

But in neither case does the return value associated with the "yield"
statement have anything directly to do with the declared return type of
the method. An iterator method must return IEnumerable, IEnumerator, or
the generic versions of those interfaces. The type of the "yield return"
statement determines the type of the data returned by the Current property
of the relevant enumerator interface. The _presence_ of a "yield"
statement requires that enumerable/enumerator return value, and the type
actually returned by the "yield" statement determines what Current returns
(boxed, if necessary).

For more information, if you haven't already you may want to read the
description of C# iterators:
http://msdn.microsoft.com/en-us/library/dscyy5s0.aspx (there's a link to
that document from the doc page for "yield" that you mentioned)

Pete

gnewsgroup

unread,
May 11, 2008, 11:02:31 PM5/11/08
to
On May 11, 7:51 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> On Sun, 11 May 2008 16:10:23 -0700, gnewsgroup <gnewsgr...@gmail.com>
> description of C# iterators: http://msdn.microsoft.com/en-us/library/dscyy5s0.aspx(there's a link to

> that document from the doc page for "yield" that you mentioned)
>
> Pete

Thank you Peter for the detailed explanation. I think things are
getting much clearer now. The iterator article, albeit short, is very
helpful. I will re-read your explanation and practice a little to
thoroughly understand this whole thing. Thanks again.

Jon Skeet [C# MVP]

unread,
May 12, 2008, 1:21:41 AM5/12/08
to
gnewsgroup <gnews...@gmail.com> wrote:
> Thank you. I know IEnumerable is an interface. I didn't mean
> IEnumerable objects and arrays are exactly the same. I notice that
> quite often the constructor of an IEnumerable class takes an array as
> the argument, and I think foreach internally makes use of the MoveNext
> method. Is it the case that the core of an IEnumerable object is an
> array? Thanks.

The core of an IEnumerable object is whatever that implementation wants
to use. Sometimes it will be an array, but it certainly doesn't have to
be.

Marc Gravell

unread,
May 12, 2008, 3:17:33 AM5/12/08
to
If it helps, I answered a very similar question recently here:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3274206&SiteID=1

In particular it shows a lot of things a compiler normally hides from
you, and demonstrates an infinite sequence (Fibonacci).

Jon's book has more information on a lot of the details - and if ch 6 is
free, go get it!

Marc

gnewsgroup

unread,
May 12, 2008, 9:35:35 AM5/12/08
to

Thank you very much. I have downloaded sample chapter 6 of Mr.
Skeet's book. I hope it'll de-confuse me on this issue.

gnewsgroup

unread,
May 12, 2008, 9:40:05 AM5/12/08
to
On May 12, 1:21 am, Jon Skeet [C# MVP] <sk...@pobox.com> wrote:

Thank you, Jon. I was misled by the MSDN People example at
http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx,
which takes an array of Person. I will read Ch 6 of your in-depth
book. Thank you.

Jon Skeet [C# MVP]

unread,
May 12, 2008, 2:54:00 PM5/12/08
to
gnewsgroup <gnews...@gmail.com> wrote:
> Thank you very much. I have downloaded sample chapter 6 of Mr.
> Skeet's book. I hope it'll de-confuse me on this issue.

Cool - do post again if it doesn't help though, as much for my benefit
(in terms of improving future editions of the books) as for yours!

0 new messages