473,583 Members | 3,114 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C# Language Specification - Enumeration

Sure... IEnumerable was inconvenient suggesting a separate class to service
the enumeration, IEnumerator, and multiple operations: Current, MoveNext,
Reset. (I'll warp the definition of "operation" for a second if you don't
mind).

However, it existed within intuitive language semantics, whereas the new
"yield" keyword, while highly convenient, is also one of the most gross
warping of language concepts to date...

public IEnumerator GetEnumerator() {
foreach(foobar o in _co) yield return o;
}

So, it essentially redefines the concepts of how functions are supposed to
behave, as well as how return values interact with return types. It also
introduces the new keyword with a very specialized purpose.

One way to explain "yield", is to say that it boxes your object into an
IEnumerator, saves the execution state of your function, and also restores
the execution state the next time your function is called, even before the
keyword is invoked during regular instruction flow, so it establishes the
loop's next startup state. Therefore, it redefines the laws of instruction
sequencing, and is sort of a quantum keyword that exists in multiple spots at
once during the existance of that function.

It would make sense to have IEnumerate be an allowed combination of
IEnumerable and IEnumerator, and to add a GetNext function that can return
the proper generic variable type. Then make "yield" its own return-style
keyword:

(** Proposed Syntax:
public class Woo : IEnumerate
{
...
public object GetNext() {
if(_collection= =null) return null;
foreach(object obj in _collection) {
yield obj;
}
}
...
}
**)

This would still allow the full existing enumeration capability, but would
introduce this new style in a cleaner and more intuitive way.
Nov 17 '05 #1
4 5651
Marshal,

The problem with condensing the two interfaces into one is that you end
up losing the fact that a type can say "I can have my contained items
iterated through, and this is the mechanism by which you do it". That's
different from your interface, which says "I can have my contained items
iterated through, and ^I^ will do it". The IEnumerable/IEnumerator
functions are better, IMO, because it will allow for better encapsulation of
code, at the least.

The other problem with your proposal is that you can't tell if there are
any more items in your iteration. Yeah, you could check against return
value of GetNext for null, but if you are enumerating value types, then you
can't do this, since they can't be null (unless you use Nullable types, but
that wasn't around in 1.0, and you would have to do this ugly case logic to
determine if it was a value type or not, and then if it was null).

Using your method would end up looking something like this:

// An object, to check for null.
object o = null;

// The type of the object.
T t;

// Loop. You have to check for null here since your implementation would
return
// null if there are no items in the enumeration. The assumption here
// is that at the end of the loop, you would return null.
while ((o = collection.GetN ext()) != null)
{
// Cast to the original object.
t = (T) o;

// Do some stuff.
}

This is a little more messy than what you have to do now. First, you
need to have the object instance just to check null, and you have a nasty
assignment and comparison in the while statement. Compare that to how
foreach is expanded by the compiler using the current IEnumeration interface
(and assuming that collection implements IEnumeration):

// The type t.
T t;

while (!collection.Mo veNext())
{
// Get the value.
t = collection.Curr ent;
}

You have t, and you know if you hit the end, but without that ugliness
in between (the o variable checking for null).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Marshal" <Ma*****@discus sions.microsoft .com> wrote in message
news:17******** *************** ***********@mic rosoft.com...
Sure... IEnumerable was inconvenient suggesting a separate class to
service
the enumeration, IEnumerator, and multiple operations: Current, MoveNext,
Reset. (I'll warp the definition of "operation" for a second if you don't
mind).

However, it existed within intuitive language semantics, whereas the new
"yield" keyword, while highly convenient, is also one of the most gross
warping of language concepts to date...

public IEnumerator GetEnumerator() {
foreach(foobar o in _co) yield return o;
}

So, it essentially redefines the concepts of how functions are supposed to
behave, as well as how return values interact with return types. It also
introduces the new keyword with a very specialized purpose.

One way to explain "yield", is to say that it boxes your object into an
IEnumerator, saves the execution state of your function, and also restores
the execution state the next time your function is called, even before the
keyword is invoked during regular instruction flow, so it establishes the
loop's next startup state. Therefore, it redefines the laws of instruction
sequencing, and is sort of a quantum keyword that exists in multiple spots
at
once during the existance of that function.

It would make sense to have IEnumerate be an allowed combination of
IEnumerable and IEnumerator, and to add a GetNext function that can return
the proper generic variable type. Then make "yield" its own return-style
keyword:

(** Proposed Syntax:
public class Woo : IEnumerate
{
...
public object GetNext() {
if(_collection= =null) return null;
foreach(object obj in _collection) {
yield obj;
}
}
...
}
**)

This would still allow the full existing enumeration capability, but would
introduce this new style in a cleaner and more intuitive way.

Nov 17 '05 #2
> The problem with condensing the two interfaces into one is that you end
up losing the fact that a type can say "I can have my contained items
iterated through, and this is the mechanism by which you do it". That's
different from your interface, which says "I can have my contained items
iterated through, and ^I^ will do it". The IEnumerable/IEnumerator
functions are better, IMO, because it will allow for better encapsulation of
code, at the least.
My proposal should be equivilent with the current proposals on using
"yield", it just cleans up the syntax. In both cases, you can still use
IEnumerable and IEnumerator for the reasons you point out, and both proposals
on "yield" are used for the ^I^ will do it case anyway.
The other problem with your proposal is that you can't tell if there are
any more items in your iteration...
Again, it's basically a cleaner way of expressing the existing yield syntax,
which has no problem terminating the enumeration in magic code. I was imaging
it being used in a foreach statement.

If the GetNext function is called directly as in your example, then I would
expect it should throw an exception if the caller tries to read beyond the
end of the array. They should write something like:

(** Proposed Syntax:
collection.Rese t();
while(collectio n.HasValues) { o = collection.GetN ext(); ... }
**)

However, they should be as unlikely to do that, as they would be to call
GetEnumerator directly in the current model which uses yield. If they did so
in the current model, it would not appear as intuitive.
Using your method would end up looking something like this:

// An object, to check for null.
object o = null;

// The type of the object.
T t;

// Loop. You have to check for null here since your implementation would
return
// null if there are no items in the enumeration. The assumption here
// is that at the end of the loop, you would return null.
while ((o = collection.GetN ext()) != null)
{
// Cast to the original object.
t = (T) o;

// Do some stuff.
}

This is a little more messy than what you have to do now. First, you
need to have the object instance just to check null, and you have a nasty
assignment and comparison in the while statement. Compare that to how
foreach is expanded by the compiler using the current IEnumeration interface
(and assuming that collection implements IEnumeration):

// The type t.
T t;

while (!collection.Mo veNext())
{
// Get the value.
t = collection.Curr ent;
}

You have t, and you know if you hit the end, but without that ugliness
in between (the o variable checking for null).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m


Nov 17 '05 #3
See inline:
The other problem with your proposal is that you can't tell if there
are
any more items in your iteration...
Again, it's basically a cleaner way of expressing the existing yield
syntax,
which has no problem terminating the enumeration in magic code. I was
imaging
it being used in a foreach statement.


Ok, so it's cleaner, but at what cost? Clean doesn't mean anything if
actually implementing it is not.
If the GetNext function is called directly as in your example, then I
would
expect it should throw an exception if the caller tries to read beyond the
end of the array. They should write something like:

(** Proposed Syntax:
collection.Rese t();
while(collectio n.HasValues) { o = collection.GetN ext(); ... }
**)
There is a specific reason why the designers of .NET didn't use
something like HasValues and GetNext. The reason for that is that a good
number of people actually forget to code the call to move to the next item
in the enumeration, leading to infinite loops. With the way it is now (with
the all to MoveNext returning whether or not there are elements), you don't
have that problem.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

However, they should be as unlikely to do that, as they would be to call
GetEnumerator directly in the current model which uses yield. If they did
so
in the current model, it would not appear as intuitive.
Using your method would end up looking something like this:

// An object, to check for null.
object o = null;

// The type of the object.
T t;

// Loop. You have to check for null here since your implementation would
return
// null if there are no items in the enumeration. The assumption here
// is that at the end of the loop, you would return null.
while ((o = collection.GetN ext()) != null)
{
// Cast to the original object.
t = (T) o;

// Do some stuff.
}

This is a little more messy than what you have to do now. First, you
need to have the object instance just to check null, and you have a nasty
assignment and comparison in the while statement. Compare that to how
foreach is expanded by the compiler using the current IEnumeration
interface
(and assuming that collection implements IEnumeration):

// The type t.
T t;

while (!collection.Mo veNext())
{
// Get the value.
t = collection.Curr ent;
}

You have t, and you know if you hit the end, but without that
ugliness
in between (the o variable checking for null).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

Nov 17 '05 #4


Marshal wrote:
Sure... IEnumerable was inconvenient suggesting a separate class to service
the enumeration, IEnumerator, and multiple operations: Current, MoveNext,
Reset. (I'll warp the definition of "operation" for a second if you don't
mind).
IEnumerable expresses that enumeration is supported, "I am iterable, you
can obtain that enumeration by invoking GetEnumerator() ".

IEnumerator expresses a "pointer" into an enumeration, "This is how far
you are along the enumeration".

IEnumerator have Current/MoveNext(), JAVA Iterator have hasNext() and
next(), C++ iterators have "++" and "*". Actually I don't recall seeing
any protocol for iteration that don't have seperate
advance/advance-check and value obtain, and thus multiple operations.

I would say that whether Reset() should be included in IEnumerator is
open to discussion.
So, it essentially redefines the concepts of how functions are supposed to
behave, as well as how return values interact with return types. It also
introduces the new keyword with a very specialized purpose.
It lets you define a generator for IEnumerator using function-syntax.
Other languages have this too, python and it is essential in ruby.

Whether this "redefines the concepts of how functions work" or not...
well, you are really just defining a function that returns an
enumerator. There is no "quantum magic" here, only compiler assisted
closure greneration.

Notice that the caller of the function doesn't care if actual "quantum
magic" was used to implement the IEnumerator returned. The implementer u
could do it by implementing the closure, MoveNext() and Current by hand
in a class that stores the relevant state and implement IEnumerator.

Function-syntax is rather nice for describing enumeration, and
syntactic-sugar support for storing the used local-variables in a
helper-class and implementing Current/MoveNext() is convinient to me in
that syntax.
One way to explain "yield", is to say that it boxes your object into an
IEnumerator, saves the execution state of your function, and also restores
the execution state the next time your function is called, even before the
keyword is invoked during regular instruction flow, so it establishes the
loop's next startup state. Therefore, it redefines the laws of instruction
sequencing, and is sort of a quantum keyword that exists in multiple spots at
once during the existance of that function.
Another way to explain it would be that it generates an IEnumerators
MoveNext() and Current functions from the closure available in the
function. This is a known technique known from functional programming: a
higher-order function.
It would make sense to have IEnumerate be an allowed combination of
IEnumerable and IEnumerator, and to add a GetNext function that can return
the proper generic variable type. Then make "yield" its own return-style
keyword:
I don't see the benefit of combining IEnumerable and IEnumerator, see above.

The problems in combining the two concepts is manifest in our
example-code. Where is _collection coming from (the interface-usage
prevents you from having a protocol of accepting it at construction time).
(** Proposed Syntax:
public class Woo : IEnumerate
{
...
public object GetNext() {
if(_collection= =null) return null;
foreach(object obj in _collection) {
yield obj;
}
}
...
}
**)

I don't really understand how this is substantially different from or
better than:

public static IEnumerator Enumerate(IColl ection c) {
foreach ( object o in c )
yield return o;
}

Which fits into the current enumeration-idiom in C#.

The choice of "yield return" vs. just "yield" is open to discussion, but
i suspect "yield return" was chosen because no program containing that
sequence of tokens would be valid in previous C# revisions.
This would still allow the full existing enumeration capability, but would
introduce this new style in a cleaner and more intuitive way.


Perhaps you are finding the IEnumerable/IEnumerator design
non-intuitive, and perhaps transfer that onto the "yield return" construct?

I find that the IEnumerable/IEnumerator design is spot-on and I haven't
really seen any languages which doesn't make that distinction in one
form or another.

Perhaps you need just a little more assimilation before you accept the
design ;) (notice smiley.... i'm not being hostile here)

--
Helge Jensen
mailto:he****** ****@slog.dk
sip:he********* *@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Nov 17 '05 #5

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

Similar topics

1
1520
by: Andrew James | last post by:
Gentlemen, I'm currently in the process of designing a language which will be used to specify sets of files on a WebDAV server, encoded in a URL. The aims of the language are to (in no particular order): * Be concise, aesthetic and easy to type * Be as similar as possible to existing query languages * Allow for (nested) boolean operations *...
1
12625
by: Justin Wright | last post by:
I know that I can set up an enumeration as follows ( just typed in quick so may have syntax errors ): <xsd:simpleType name="colors"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="red"/> <xsd:enumeration value="yellow"/> <xsd:enumeration value="blue"/> </xsd:simpleType>
63
5843
by: Tristan Miller | last post by:
Greetings. Do any popular browsers correctly support <q>, at least for Western languages? I've noticed that Mozilla uses the standard English double-quote character, ", regardless of the lang attribute of the HTML document. Will any browsers render German-style quotes or French-style guillemots for lang="de" and lang="fr", respectively? ...
86
3887
by: Randy Yates | last post by:
In Harbison and Steele's text (fourth edition, p.111) it is stated, The C language does not specify the range of integers that the integral types will represent, except ot say that type int may not be smaller than short and long may not be smaller than int. They go on to say, Many implementations represent characters in 8 bits, type...
6
2329
by: Tony Whitter | last post by:
Does anyone know how much changed between the final draft dated October 2002 and the Ecma-334 C# Language Specification 2nd edition dated December 2002 and if there is a change history document anywhere? Thanks in anticipation. Tony
42
2159
by: Eric Gunnerson [MS] | last post by:
You may download the new specification at the C# Developer Center (http://msdn.microsoft.com/vcsharp/language). There is a discussion forum for the C# language on that same page. If you don't own a copy of MS Word, you can download the free viewer at: ...
0
1145
by: Marshal [DirectX MVP 2003] | last post by:
In anticipation of the chat, I have filtered all of my current enhancement aleration ideas through the software development community, via the following postings: C# Language Specification - Delegates C# Language Specification - Extension Methods C# Language Specification - Enumeration C# Language Specification - Generics If anybody...
3
1695
by: albert.neu | last post by:
Hello! What is the difference between "library parts" of C99 and "language parts" of C99. see http://groups.google.at/group/microsoft.public.vc.language/browse_thread/thread/e9a67f0ff20a954b/bd2bada2bbdbce56?lnk=st&rnum=1#bd2bada2bbdbce56 I know that "Dinkum Compleat Libraries" (http://www.dinkumware.com/) support the "library parts"...
2
1701
by: Vneha | last post by:
Q:- What is the difference between Sun Java tutorials and Java Language specification? Q:- What if i start studying Java Language Specification and leave the tutorials because i have seen that Java Language Specification is much more in detail and covers all the topic that are in Java tutorials.? Regards, Neha
0
7896
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
8328
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7936
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8195
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5701
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5375
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3845
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2334
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1434
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.