473,386 Members | 1,798 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,386 software developers and data experts.

Enumerators

I am currently writing a class which I would like to make "enumerable" by
inheriting from IEnumerable. The documentation says that the
IEnumerator.MoveNext method should throw an exception if the object being
enumerated has changed since the enumerator was created. Does anyone have
any tips on how best to implement this?

I can think of 2 approaches, neither of which seem very satisfactory. These
are as follows:

1. Take a copy of the class being enumerated when the enumerator is created.
This would be a complete copy, not just a copy of the reference. Then, every
time MoveNext is called, it could compare the current contents to that when
the enumerator was created. This would have a potentially enormous overhead.

2. Have the class being enumerated keep a list of all currently live
enumerators. The class would then inform the enumerators if its contents
changed. This seems like a lot of work to implement something which you
might expect to be straightforward.

An alternative would be to not bother throwing this exception at all.
However this would then break the IEnumerable and IEnumerator specification
which might be considered bad practice.

Thanks,
Tim Davis
Nov 16 '05 #1
6 2008

"Tim Davis" <td***********@ntlworld.com> wrote in message
news:rH**************@newsfe2-gui.ntli.net...
I am currently writing a class which I would like to make "enumerable" by
inheriting from IEnumerable. The documentation says that the
IEnumerator.MoveNext method should throw an exception if the object being
enumerated has changed since the enumerator was created. Does anyone have
any tips on how best to implement this?

I can think of 2 approaches, neither of which seem very satisfactory.
These
are as follows:


Personally, I usually use a private version field in the object and change
the version on every modification. When you create an enumerator, you copy
the version value and compare your copy and the objects on every iteration,
if the version changes you have a changed collection.

Depending on your needs, you can probably either use a ulong and simply
increment each time or you could generate GUID's for each version. That
choice is yours.

For what its worth, you should be able to safely change an object without
causing IEnumerator to crash if and only if that change doesn't effect the
results IEnumerator returns. I don't think there is a reason to issue an
exception if some property unrelated to the enumerated contents is set.
Nov 16 '05 #2
Perhaps I'm missing the point, but IEnumerable classes are containers, like
ArrayList and Stack. We don't care if one of the objects within the
container is modified, only if the list itself has been modified (by adding,
deleting, or in some way reordering the list).

Therefore, in your class, set a "dirty" flag if any of these operations
occurs. Clear the "dirty" flag when the enumerator is initialized, and
check it on every MoveNext method call. If it has been set (by the code
adding an entry), throw the error.

Not difficult to implement.

--- Nick

"Tim Davis" <td***********@ntlworld.com> wrote in message
news:rH**************@newsfe2-gui.ntli.net...
I am currently writing a class which I would like to make "enumerable" by
inheriting from IEnumerable. The documentation says that the
IEnumerator.MoveNext method should throw an exception if the object being
enumerated has changed since the enumerator was created. Does anyone have
any tips on how best to implement this?

I can think of 2 approaches, neither of which seem very satisfactory. These are as follows:

1. Take a copy of the class being enumerated when the enumerator is created. This would be a complete copy, not just a copy of the reference. Then, every time MoveNext is called, it could compare the current contents to that when the enumerator was created. This would have a potentially enormous overhead.
2. Have the class being enumerated keep a list of all currently live
enumerators. The class would then inform the enumerators if its contents
changed. This seems like a lot of work to implement something which you
might expect to be straightforward.

An alternative would be to not bother throwing this exception at all.
However this would then break the IEnumerable and IEnumerator specification which might be considered bad practice.

Thanks,
Tim Davis

Nov 16 '05 #3

"Nick Malik" <ni*******@hotmail.nospam.com> wrote in message
news:gE7Rc.218528$a24.115525@attbi_s03...
Perhaps I'm missing the point, but IEnumerable classes are containers,
like
ArrayList and Stack. We don't care if one of the objects within the
container is modified, only if the list itself has been modified (by
adding,
deleting, or in some way reordering the list).

Therefore, in your class, set a "dirty" flag if any of these operations
occurs. Clear the "dirty" flag when the enumerator is initialized, and
check it on every MoveNext method call. If it has been set (by the code
adding an entry), throw the error.


There is an issue here with an ordinary boolean dirty flag. Its possible
that a person could generate an IEnumerator, make a change, and generate
another IEnumerator which would reset the dirty flag and would then not
throw an exception when the first IEnumerator calls MoveNext(), even though
it should. Thats why I recommend a full version approach, every change
results in a unique version and every IEnumerator has the version it works
with. You don't have to worry about usage nuances like this. You do have to
consider the maximum enumerations, however, UInt64 allows you to have *ALOT*
of versions.

Nov 16 '05 #4
I don't think this would work if two enumerators were used at the same time.

Consider the following:
Enumerator1 is initialized and the dirty flag is set to clean.
MoveNext is called.
The IEnumerable derivative is then modified so the dirty flag is set to
"dirty".
Enumerator2 is initialized - the dirty flag is then reset to "clean".
When Enumerator1.MoveNext is called again, it wrongly thinks the IEnumerable
derivative is clean.

Regards,
Tim

"Nick Malik" <ni*******@hotmail.nospam.com> wrote in message
news:gE7Rc.218528$a24.115525@attbi_s03...
Perhaps I'm missing the point, but IEnumerable classes are containers, like ArrayList and Stack. We don't care if one of the objects within the
container is modified, only if the list itself has been modified (by adding, deleting, or in some way reordering the list).

Therefore, in your class, set a "dirty" flag if any of these operations
occurs. Clear the "dirty" flag when the enumerator is initialized, and
check it on every MoveNext method call. If it has been set (by the code
adding an entry), throw the error.

Not difficult to implement.

--- Nick

Nov 16 '05 #5
Sounds like a good idea.

Thanks,
Tim

"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:uP**************@TK2MSFTNGP11.phx.gbl...

"Tim Davis" <td***********@ntlworld.com> wrote in message
news:rH**************@newsfe2-gui.ntli.net...
I am currently writing a class which I would like to make "enumerable" by
inheriting from IEnumerable. The documentation says that the
IEnumerator.MoveNext method should throw an exception if the object being enumerated has changed since the enumerator was created. Does anyone have any tips on how best to implement this?

I can think of 2 approaches, neither of which seem very satisfactory.
These
are as follows:

Personally, I usually use a private version field in the object and change
the version on every modification. When you create an enumerator, you copy
the version value and compare your copy and the objects on every

iteration, if the version changes you have a changed collection.

Depending on your needs, you can probably either use a ulong and simply
increment each time or you could generate GUID's for each version. That
choice is yours.

For what its worth, you should be able to safely change an object without
causing IEnumerator to crash if and only if that change doesn't effect the
results IEnumerator returns. I don't think there is a reason to issue an
exception if some property unrelated to the enumerated contents is set.

Nov 16 '05 #6
This actually is a point that gets very involved when you start dealing with
data binding, but I've found using a base class, or interface works quite
well. I just finished writing *ahem* super extended collection base class
from way over the mountain.

In it, I keep a guid that only changes when members are added or removed
from the collection. In additon, the objects it holds implement an
interface (I derived a new one from IEditableObject that adds an
EditStateChanged event). Any time an object in added to the collection, the
collection links on an event handlers and removes it when the item is
removed. The event is raised by the object when it 'changes' and that
causes the collection to also trigger is guid change. Then IEnumerable
implementation just stored the original guid and compares it the the one
currently in the collection before it does an operation. You could use and
other flagging type mechanism also.

If you were using structs in your collection, then you could do a hash on
the entire set and have a good idea that something has changed, but objects
dont change the hash because the default hash (i believe) only compares the
object references. All of this becomes big issues if and when you start
implementing the IBindingList interface.

Hope this helps, a little at least.
"Tim Davis" <td***********@ntlworld.com> wrote in message
news:er*************@newsfe2-gui.ntli.net...
I don't think this would work if two enumerators were used at the same time.
Consider the following:
Enumerator1 is initialized and the dirty flag is set to clean.
MoveNext is called.
The IEnumerable derivative is then modified so the dirty flag is set to
"dirty".
Enumerator2 is initialized - the dirty flag is then reset to "clean".
When Enumerator1.MoveNext is called again, it wrongly thinks the IEnumerable derivative is clean.

Regards,
Tim

"Nick Malik" <ni*******@hotmail.nospam.com> wrote in message
news:gE7Rc.218528$a24.115525@attbi_s03...
Perhaps I'm missing the point, but IEnumerable classes are containers,

like
ArrayList and Stack. We don't care if one of the objects within the
container is modified, only if the list itself has been modified (by

adding,
deleting, or in some way reordering the list).

Therefore, in your class, set a "dirty" flag if any of these operations
occurs. Clear the "dirty" flag when the enumerator is initialized, and
check it on every MoveNext method call. If it has been set (by the code
adding an entry), throw the error.

Not difficult to implement.

--- Nick


Nov 16 '05 #7

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

Similar topics

2
by: Bob Shafer | last post by:
Is it possible to create dynamic enumerators in Visual Basic .Net? For example, an enumurator that provides a dropdown of available SQL servers?
6
by: Matt Taylor | last post by:
I'm trying to write an x86 assembler in C++ for use in a debugger. What I'd like do is to use template specialization to prevent invalid combinations from compiling. Thus one could not accidentally...
1
by: Dave | last post by:
I have several enums that are generated by a code generator (and I have no control over the code generator), the problem is that the names are pretty long enum VeryLoooooooongEnumName {...
2
by: Peter Rilling | last post by:
A design pattern question. As you know, an enumerator in .NET is broken into two interface (IEnumerable and IEnumerator). Is there a benefit in having two interfaces? Why not just have the...
2
by: Andrew Quine | last post by:
Hi Short one: looking for a good example and an explanation of such enumerators. I know MessageEnumerator and ResourceReader do this, for example, but what is the implementation of the...
5
by: juan | last post by:
hi i have an arraylist that has doctor objects with various properties, members and methods. i want to enumerate this arraylist object. but i dont understand how. this is what i have done ...
2
by: psbasha | last post by:
Hi , Does Python supports enumerators? enum{ Red=1, Gren, Blue, Orange}
1
muaddubby
by: muaddubby | last post by:
Hello all and happy new year. I've seen several posts floating around asking about string enumerators in C#, and generally speaking, they're not supported. I've come up with a way around it...
1
nitindel
by: nitindel | last post by:
Hi All, May i have an in depth article of enumerators in C#..that explains the Enumerators in C# very precisely.... Thanks, Nitin
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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...
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
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
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,...

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.