473,769 Members | 2,222 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

IEnumerator Usage

I've been kicking around an idea mostly as a thought experiment at this
point. The idea is to create a thread safe collection that implements
the IEnumerable interface. The enumerators it creates via the
GetEnumerator method would be synchronized with the collction; if the
collection changes, the existing enumerators are notified via an event.
The accompanying EventArgs derived class object carries information
about the change to the collection so that the enumerators can update
themselves to keep the enumerations in sync.

This type of approach allows enumeration over a collection while it is
being changed without an exception being thrown. This type of approach
may be useful to me at some point in the future.

My question is this: the IEnumerator interface specification for the
MoveNext method states that an InvalidOperatio nException will be thrown
if the collection is modified after the enumerator was created. Using
the approach I described above, this would no longer be the case. So
would it be considered bad design to implement the IEnumerator interface
but not enforce this precondition? Should I abandon implementing the
IEnumerator interface?

The advantage of using the IEnumerator interface is it allows
enumerators to be used seamlessly with the foreach construct, so I would
really like to use it but have my doubts about weakening the IEnumerator
specification. Thoughts?
May 17 '06 #1
11 2218
"Leslie Sanford" <ja**********@B iteMeHotmail.co m> wrote:
My question is this: the IEnumerator interface specification for the
MoveNext method states that an InvalidOperatio nException will be thrown
if the collection is modified after the enumerator was created. Using
the approach I described above, this would no longer be the case. So
would it be considered bad design to implement the IEnumerator interface
but not enforce this precondition?


No!

That's my take on it. Also think of "yield return" and iterator
blocks, which offer the IEnumerator interface even though they don't
even have a collection at all.

I've even used IEnumerator to enumerate over values that must be
removed from a collection, where I *require* the value to be removed
from the collection before calling MoveNext. (because that was how the
"must-be-removed" algorithm worked). (nb. with values rather than
references.)

--
Lucian
May 17 '06 #2
It is a bad design. When you iterate over a collection you are
interested in the collection's state at the moment you invoked the
iteration (these are the semantics).

Imagine having to take a decision a particular moment about an event
while iterating a collection that you cannot be sure if it has been
changed or not.

If you want to create a producer/consumer pattern you should consider
an alternative design.

As the MSDN documentation states "Enumeratin g through a collection is
intrinsically not a thread-safe procedure".

Regards,
Tasos

May 17 '06 #3

"Tasos Vogiatzoglou" wrote:
It is a bad design. When you iterate over a collection you are
interested in the collection's state at the moment you invoked the
iteration (these are the semantics).

Imagine having to take a decision a particular moment about an event
while iterating a collection that you cannot be sure if it has been
changed or not.
Consider this example: Suppose you have a program for playing/editing
MIDI files (my area of expertise). MIDI files are made up of tracks
which are themselves made up of MIDI events. In other words, each track
is a collection of MIDI events.

Say that you would like to edit a track as it is being played. For
example, you may want to move an event forward in time or delete it.

Playing a MIDI file essentially involves iterating over the collection
of MIDI events in each track (with the speed of the iteration being
driven by timing events). If you want to edit these tracks as they are
being played, you are modifying a collection as it is being iterated
over.

So with the above scenario, I was thinking of creating iterators that
are capable of keeping themselves in sync with the track collections as
they are being modified.

IEnumerator aside, would this be considered bad design?
If you want to create a producer/consumer pattern you should consider
an alternative design.
Hmm, I will study the producer/consumer approach. Given the above
description, can you suggest a way of applying producer/consumer to my
problem?
As the MSDN documentation states "Enumeratin g through a collection is
intrinsically not a thread-safe procedure".


This is true of true of the collection classes provided by the .NET
framework, but does it have to hold true for your own custom collection
classes?
May 17 '06 #4
A "rough" approach (if I understood the problem correctly):

You have collection A that holds MIDI events. You have a thread PLAYER
that iterates through the collection at specified intervals. If you
modify collection A at position POS you can notify the PLAYER to stop
the iteration and begin again at the position that stopped. That way
the PLAYER will get the latest change (if it was at the position of
editing).

This could be one approach without having to resort to a IEnumerable
that ignores collection changes.

I don't think that producer/consumer applies well to this problem.

The rules are meant to be broken of course and because .NET
documentation says so this doesn't mean that you can't create such a
collection. But I personally believe that this may introduce bugs that
are not immediately visible ( or addressable) .

Regards,
Tasos

May 17 '06 #5
"Leslie Sanford" <ja**********@B iteMeHotmail.co m> schrieb im Newsbeitrag
news:_p******** *************** *******@comcast .com...
I've been kicking around an idea mostly as a thought experiment at this
point. The idea is to create a thread safe collection that implements the
IEnumerable interface. The enumerators it creates via the GetEnumerator
method would be synchronized with the collction; if the collection
changes, the existing enumerators are notified via an event. The
accompanying EventArgs derived class object carries information about the
change to the collection so that the enumerators can update themselves to
keep the enumerations in sync.

This type of approach allows enumeration over a collection while it is
being changed without an exception being thrown. This type of approach may
be useful to me at some point in the future.

<snip>

Hi Leslie,

i think the greatest problem with this is, clearly defining the semantic.
I mean, how should the enumerator react if certain changes occur in the
underlying list. If that's clearly defined than your approach could work.
But maybe Tasos is right, that Enumarator is not the design for your
solution

HTH
Christof
May 17 '06 #6
Leslie,

I agree with the majority of the opinions here that it is bad design.
The interface implies a contract, and you are violating that. It's not
something to be taken lightly, IMO. There are semantics that users of the
iterface you implement assume, and if you violate that, then their claims
about what they can do can't be enforced, and so on and so on.

To make your collection thread safe, I would offer one of the following:

- Throw an exception when the enumeration is changed
- Use locks to block changes on the collection while it is being enumerated
- Take a snapshot of the collection while enumerating and have the
enumerator use that instead of the store that is being modified.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Leslie Sanford" <ja**********@B iteMeHotmail.co m> wrote in message
news:_p******** *************** *******@comcast .com...
I've been kicking around an idea mostly as a thought experiment at this
point. The idea is to create a thread safe collection that implements the
IEnumerable interface. The enumerators it creates via the GetEnumerator
method would be synchronized with the collction; if the collection
changes, the existing enumerators are notified via an event. The
accompanying EventArgs derived class object carries information about the
change to the collection so that the enumerators can update themselves to
keep the enumerations in sync.

This type of approach allows enumeration over a collection while it is
being changed without an exception being thrown. This type of approach may
be useful to me at some point in the future.

My question is this: the IEnumerator interface specification for the
MoveNext method states that an InvalidOperatio nException will be thrown if
the collection is modified after the enumerator was created. Using the
approach I described above, this would no longer be the case. So would it
be considered bad design to implement the IEnumerator interface but not
enforce this precondition? Should I abandon implementing the IEnumerator
interface?

The advantage of using the IEnumerator interface is it allows enumerators
to be used seamlessly with the foreach construct, so I would really like
to use it but have my doubts about weakening the IEnumerator
specification. Thoughts?

May 17 '06 #7

"Tasos Vogiatzoglou" wrote:
A "rough" approach (if I understood the problem correctly):

You have collection A that holds MIDI events. You have a thread PLAYER
that iterates through the collection at specified intervals. If you
modify collection A at position POS you can notify the PLAYER to stop
the iteration and begin again at the position that stopped. That way
the PLAYER will get the latest change (if it was at the position of
editing).

This could be one approach without having to resort to a IEnumerable
that ignores collection changes.


This is a good suggestion. Instead of trying to shoehorn
IEnumerable/IEnumerator into my design, I could instead have a class
dedicated to playback and keeping track of changes to the collection so
that the playback is synchronized. Thanks for your response.
May 17 '06 #8
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om>
wrote:
I agree with the majority of the opinions here that it is bad design.
The interface implies a contract, and you are violating that.


It's an odd sort of contract, though. This contract that you're
violating is a contract about what ISN'T supported (modifying the
collection in flight), rather than one about what IS supported. So the
only clients who would be affected by the proposal are those who
*rely* upon the "CollectionChan ged" exception. And I'd call those
clients broken.

--
Lucian
May 18 '06 #9
Lucian,
At first it may seem like an odd contract, but you are not violating a
contract about what is not supported, you violate the intented usage
pattern.

If you bring new developers to your project, when they will see a
collection they will assume that they can iterate the collection just
keeping in mind the case of concurrent modifications. But by violating
that contract, you give to your co-developers an IEnumerable with
broken semantics.

Noone excpects an infite loop for example for a collection enumeration,
something that can happen if you violate the (implied at least)
pattern.

Regards,
Tasos

May 18 '06 #10

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

Similar topics

9
1844
by: Sasha | last post by:
Hi, I am extending standard IEnumerator, and I was just wondering what is the best way to make enumarator safe? What do I mean by safe? Detect deletes and all... My idea is to have private Guid state field in the collection, and every time something is inserted or deleted from the collection, I will just change the guid. Enumerator will just have to compare the guid received in the begging to the current one. If they are different, the...
1
2126
by: juan | last post by:
hi i have a teachers class where i want the user to enter a few teachers and iterate thru them. In the main i get an error System.Collections.IEnumerator' does not contain a definition for 'Length' why is that? is this approach right? I want to develop an OO App. so is this approach right?
3
7124
by: Hans | last post by:
I implemented the IEnumerator interface in some classes to enable the use of the foreach statement. As you probalbly know, the interface asks for the implementation of object IEnumerator.Curren bool IEnumerator.MoveNext() an void IEnumerator.Reset() The help to IEnumerator.MoveNext describes that "after the end of the collection is passed, subsequent calls to MoverNect return false until reset is called" When, however, I have two...
3
4329
by: starter | last post by:
I am trying to learn IEnumerator and collections(ArrayList, Hashtable) in .NET. Can anyone tell me what is IEnumerator used for and any online resources would be helpful. Thanks
1
3703
by: midnight madness | last post by:
I tried but failed to implement a template class that support IEnumerator<T> interface using C++/CLI in VS 2005 Professional version. I could not figure out the proper syntax to implement the property "Current". The challange is that I need to implement two versions of the property: one of type System::Object as required by Collections::IEnumerator, the other of type T^ as required by Collections::Generic::IEnumerator<T> ...
5
9375
by: Shikari Shambu | last post by:
Hi, I am trying to implement a collection that implements IEnumerable<T>. I keep getting the following error 'IEnumerator<...>.Current' in explicit interface declaration is not a member of interface. Please help me resolve the error I was able to implement the non Generics version
3
5768
by: EmilH | last post by:
Hi. I have read some examples of IEnumerator at http://www.codeproject.com/csharp/csenumerators.asp What if I have 2 arrays or collections, for example a DataSet which has 2 DataTables in my class which derives from IEnumerator? How to implement Current property to return current item of the desired DataTable? Thanks. Emil.
3
2006
by: cody | last post by:
Currently it is only legal to use types which has a method named GetEnumerator to be used in a foreach loop. This makes it impossible to use the same Enumerator after and before a foreach loop, because GetEnumerator always returns a new one. My proposal would allow the following scenario: You could for example the first and the last element of the list as a special case:
2
11786
by: Henri.Chinasque | last post by:
I have a feeling this is a dumb one, but here it is: IEnumerator<Timplements IDisposable, but the thing is I'm not sure what I'm supposed to dispose! I'm also curious why IEnumerator<T> implements IDisposable, but not IEnumerator. Anyone? Thanks, HC
0
10223
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10051
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 captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10000
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 most users, this new feature is actually very convenient. If you want to control the update process,...
0
9866
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 choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7413
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 instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6675
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 into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5448
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3968
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
3
2815
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.