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

Ameliorations in the Collections framework in .NET 2

Hello all,

One area where the .Net framework 1.1 is really poor is Collections : We've
got very few choice concerning the containers and their characteristics (for
example, ArrayList, Queue and Stack are the only "non-dictionary" avalaible
containers, and only Stack has some complexity specifications).

The worst thing however is the IEnumerator interface, which doesn't allow
for insertion, deletion or even *modification* of an item during
enumeration.
This makes IEnumerator (and therefore foreach in C#) almost unusable in most
cases, which may be why most programmers still use "for" loops, with the
obvious danger of index "off by one" error, etc...
The only workaround I found on the net is
http://msdn.microsoft.com/library/de...rp01212002.asp,
but this is mostly unacceptable (do a copy of the whole collection - even a
shallow copy - for each enumeration! By Jove!!! How awfull!)
..NET 2 is already a great step forward with strongly typed generics
collections and the addition of a *few* more containers (LinkedList,
SortedDictionnary, and... that's all!). However, it seems there is still no
formal compexity specifications for all operations on the containers...
More important, the IEnumerator is still limited to reading the container :
The Generic.IEnumerator doc states that modifying a container during
enumeration is "undefined behaviour" (gee, they begin to borrow the C++
standardese language!), but for all the *provided* containers, modifying the
container during enumeration is invalid. For example, the
LinkedList.Enumerator's doc states :
"An enumerator remains valid as long as the collection remains unchanged. If
changes are made to the collection, such as adding, modifying, or deleting
elements, the enumerator is irrecoverably invalidated and its behavior is
undefined."
Heeks! What's the advantage of a doubly linked list over an array if you
cannot insert or delete items in the middle of the container at will ??

Compared with the STL, where each container defines when and how iterators
are invalidated, the IEnumerator model is extremly poor and almost unusable
as soon as you do non-trivial manipulations on the containers. Does anyone
know wether some ameliorations will be provided in this area, and if so,
when ? (I do not think we will see anything new in Visual 2005 Gold, but
perhaps after...). Short of that, I am pondering about implementing my own
collections framework, more inspired by the STL or other libraries; However,
only Microsoft can provide the "top-level", much usefull, facilites such as
foreach...

Arnaud
MVP - VC
Oct 12 '05 #1
8 1764
Arnaud Debaene wrote:
The worst thing however is the IEnumerator interface, which doesn't allow
for insertion, deletion or even modification of an item during enumeration.
This makes IEnumerator (and therefore foreach in C#) almost unusable in
most cases, which may be why most programmers still use "for" loops, with
the obvious danger of index "off by one" error, etc...


I'm with you in your assessment of the problem - I would very much like
these restrictions to be lifted. Just wanted to quickly comment on '...
which may be why most programmers still use "for" loops ...' - I estimate
I use foreach about 95% of the time, if not more often, and this is the
same in most of the .NET code I've seen written by other people. The loops
I write that don't need to make any changes to the list's content
outnumber the ones that do by far, so I definitely find the foreach
statement extremely useful in its current form - not that it couldn't be
even more useful, but that would also raise the level of complexity when
implementing collections or custom iterators.
Oliver Sturm
--
Expert programming and consulting services available
See http://www.sturmnet.org (try /blog as well)
Oct 13 '05 #2
I wouldn't expect much as this is likely "by design". The last time I saw
something about that the explanation was that updating the collection you
are enumerating is like "cutting the branch on which you are sit"...

I didn't take the time to dive into gory details but for example if you
remove the current node from a linked list, it's seem quite logical to
update it's next/previous pointer and the enumerator doesn't have any more
the information allowing to jump to the next element. You'll likely find
those details by Googling...

--
Patrice

"Arnaud Debaene" <ad******@club-internet.fr> a écrit dans le message de
news:uJ**************@TK2MSFTNGP10.phx.gbl...
Hello all,

One area where the .Net framework 1.1 is really poor is Collections : We've got very few choice concerning the containers and their characteristics (for example, ArrayList, Queue and Stack are the only "non-dictionary" avalaible containers, and only Stack has some complexity specifications).

The worst thing however is the IEnumerator interface, which doesn't allow
for insertion, deletion or even *modification* of an item during
enumeration.
This makes IEnumerator (and therefore foreach in C#) almost unusable in most cases, which may be why most programmers still use "for" loops, with the
obvious danger of index "off by one" error, etc...
The only workaround I found on the net is
http://msdn.microsoft.com/library/de...rp01212002.asp, but this is mostly unacceptable (do a copy of the whole collection - even a shallow copy - for each enumeration! By Jove!!! How awfull!)
.NET 2 is already a great step forward with strongly typed generics
collections and the addition of a *few* more containers (LinkedList,
SortedDictionnary, and... that's all!). However, it seems there is still no formal compexity specifications for all operations on the containers...
More important, the IEnumerator is still limited to reading the container : The Generic.IEnumerator doc states that modifying a container during
enumeration is "undefined behaviour" (gee, they begin to borrow the C++
standardese language!), but for all the *provided* containers, modifying the container during enumeration is invalid. For example, the
LinkedList.Enumerator's doc states :
"An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting
elements, the enumerator is irrecoverably invalidated and its behavior is
undefined."
Heeks! What's the advantage of a doubly linked list over an array if you
cannot insert or delete items in the middle of the container at will ??

Compared with the STL, where each container defines when and how iterators
are invalidated, the IEnumerator model is extremly poor and almost unusable as soon as you do non-trivial manipulations on the containers. Does anyone
know wether some ameliorations will be provided in this area, and if so,
when ? (I do not think we will see anything new in Visual 2005 Gold, but
perhaps after...). Short of that, I am pondering about implementing my own
collections framework, more inspired by the STL or other libraries; However, only Microsoft can provide the "top-level", much usefull, facilites such as foreach...

Arnaud
MVP - VC

Oct 13 '05 #3

Patrice wrote:
I wouldn't expect much as this is likely "by design". The last time I saw
something about that the explanation was that updating the collection you
are enumerating is like "cutting the branch on which you are sit"...

I didn't take the time to dive into gory details but for example if you
remove the current node from a linked list, it's seem quite logical to
update it's next/previous pointer and the enumerator doesn't have any more
the information allowing to jump to the next element. You'll likely find
those details by Googling...


The answer is quite simple : when deleting an item from a linked list,
only those iterators/enumerators pointing to the deleted node are
invalidated. The "delete" method can return an iterator/enumerator
pointing to the next element remaining after the deletetiion. This is
what std::list::erase does in C++.

Arnaud
MVP - VC

Oct 13 '05 #4
Arnaud,

Invalidation of the enumerator is a non issue for me most of the time
since I rarely need to modify a collection during enumeration. It's
more likely for me that I fall back on a normal for loop when I need to
know the position of the item in the enumeration. Of course, you
cannot use a normal for loop on IDictionary or anything other than
IList or an array so we're left with declaring and incrementing our own
loop counters manually in that case.

The SortedList quicksorts the entire collection on every insert and
delete operation making it frightfully slow. I've asked this before
and I'll ask it again. Why, oh why, did they not provide a red black
tree implementation?

Where's the priority queue?

Has anyone found the ListDictionary or HybridDictionary useful? I've
never used either one. Yeah, I know why they're there, it's just that
a normal Hashtable has proven satisfactory in all cases for me.

Brian

Arnaud Debaene wrote:
Hello all,

One area where the .Net framework 1.1 is really poor is Collections : We've
got very few choice concerning the containers and their characteristics (for
example, ArrayList, Queue and Stack are the only "non-dictionary" avalaible
containers, and only Stack has some complexity specifications).

The worst thing however is the IEnumerator interface, which doesn't allow
for insertion, deletion or even *modification* of an item during
enumeration.
This makes IEnumerator (and therefore foreach in C#) almost unusable in most
cases, which may be why most programmers still use "for" loops, with the
obvious danger of index "off by one" error, etc...
The only workaround I found on the net is
http://msdn.microsoft.com/library/de...rp01212002.asp,
but this is mostly unacceptable (do a copy of the whole collection - even a
shallow copy - for each enumeration! By Jove!!! How awfull!)
.NET 2 is already a great step forward with strongly typed generics
collections and the addition of a *few* more containers (LinkedList,
SortedDictionnary, and... that's all!). However, it seems there is still no
formal compexity specifications for all operations on the containers...
More important, the IEnumerator is still limited to reading the container :
The Generic.IEnumerator doc states that modifying a container during
enumeration is "undefined behaviour" (gee, they begin to borrow the C++
standardese language!), but for all the *provided* containers, modifying the
container during enumeration is invalid. For example, the
LinkedList.Enumerator's doc states :
"An enumerator remains valid as long as the collection remains unchanged. If
changes are made to the collection, such as adding, modifying, or deleting
elements, the enumerator is irrecoverably invalidated and its behavior is
undefined."
Heeks! What's the advantage of a doubly linked list over an array if you
cannot insert or delete items in the middle of the container at will ??

Compared with the STL, where each container defines when and how iterators
are invalidated, the IEnumerator model is extremly poor and almost unusable
as soon as you do non-trivial manipulations on the containers. Does anyone
know wether some ameliorations will be provided in this area, and if so,
when ? (I do not think we will see anything new in Visual 2005 Gold, but
perhaps after...). Short of that, I am pondering about implementing my own
collections framework, more inspired by the STL or other libraries; However,
only Microsoft can provide the "top-level", much usefull, facilites such as
foreach...

Arnaud
MVP - VC


Oct 13 '05 #5

Brian Gideon wrote:
Arnaud,

Invalidation of the enumerator is a non issue for me most of the time
since I rarely need to modify a collection during enumeration. Don't you ever do operations of the kind "delete from this container
all items that are equals to <X> or that satisfy <Y> predicate" ?
It's
more likely for me that I fall back on a normal for loop when I need to
know the position of the item in the enumeration. Of course, you
cannot use a normal for loop on IDictionary or anything other than
IList or an array so we're left with declaring and incrementing our own
loop counters manually in that case. Yep, and we all know that manual loop counters are dangerous and a
source of infinite trouble, especially if we add or remove items from
the container during enumeration.

The SortedList quicksorts the entire collection on every insert and
delete operation making it frightfully slow. I've asked this before
and I'll ask it again. Why, oh why, did they not provide a red black
tree implementation? You've got it in .NET 2 with SortedDictionnary, but nothing for "non
dictionnary" containers:-( What really miss here is the equivalent of
std::set and std::multi_set in C++...


Where's the priority queue?

Has anyone found the ListDictionary or HybridDictionary useful? I've
never used either one. Yeah, I know why they're there, it's just that
a normal Hashtable has proven satisfactory in all cases for me.


For small data sets, I would say that list dictionnary is faster than
Hadhtable (no need to calculate hashs....)

Arnaud
MVP - VC

Oct 13 '05 #6
ad******@club-internet.fr wrote:
Brian Gideon wrote:
Arnaud,

Invalidation of the enumerator is a non issue for me most of the time
since I rarely need to modify a collection during enumeration.


Don't you ever do operations of the kind "delete from this container
all items that are equals to <X> or that satisfy <Y> predicate" ?


Sure, but for me it just doesn't happen very much. I do see where
you're coming from though.
It's
more likely for me that I fall back on a normal for loop when I need to
know the position of the item in the enumeration. Of course, you
cannot use a normal for loop on IDictionary or anything other than
IList or an array so we're left with declaring and incrementing our own
loop counters manually in that case.


Yep, and we all know that manual loop counters are dangerous and a
source of infinite trouble, especially if we add or remove items from
the container during enumeration.


Also, it means the counter must be scoped outside of the foreach
construct. It seems clunky when I only intend for it to be used inside
the loop.
The SortedList quicksorts the entire collection on every insert and
delete operation making it frightfully slow. I've asked this before
and I'll ask it again. Why, oh why, did they not provide a red black
tree implementation?


You've got it in .NET 2 with SortedDictionnary, but nothing for "non
dictionnary" containers:-( What really miss here is the equivalent of
std::set and std::multi_set in C++...


That's definitely a nice addition.

Where's the priority queue?

Has anyone found the ListDictionary or HybridDictionary useful? I've
never used either one. Yeah, I know why they're there, it's just that
a normal Hashtable has proven satisfactory in all cases for me.


For small data sets, I would say that list dictionnary is faster than
Hadhtable (no need to calculate hashs....)


I'm sure it is. The documentation even says so. It's just that the
performance gain, which appears be to marginal at best, isn't a very
convincing reason in most cases. If the data set grew unexpectedly
then the performance loss would be painful if using a ListDictionary.

The HybridDictionary is a little more understandable. But for me, I've
never had a situation where I can proudly assert that performance is of
the utmost importance, but concede that the data set size, though small
in most cases, is in fact unbounded.

Oct 13 '05 #7
Arnaud Debaene wrote:
The worst thing however is the IEnumerator interface, which doesn't
allow for insertion, deletion or even *modification* of an item during
enumeration.
Well, I don't see that as a problem. Look at the name of the interface -
it is for *enumerating*. This is interface programming, each interface
has a behaviour and in the case oif IEnumerable the behaviour is clear -
it gives a serial access to the data in the collection.
which may be why most programmers still use "for"
loops, with the obvious danger of index "off by one" error, etc...
The only workaround I found on the net is
http://msdn.microsoft.com/library/de...rp01212002.asp,
but this is mostly unacceptable (do a copy of the whole collection -
even a shallow copy - for each enumeration! By Jove!!! How awfull!)


If you want to change the collection why would you want to use an
interface that enumerates objects in the collection? I understand the
issue you are trying to raise, but the problem is that you are trying to
use the interface to do something that it is specifically not supposed
to do.

Richard
--
http://www.grimes.demon.co.uk/workshops/fusionWS.htm
http://www.grimes.demon.co.uk/workshops/securityWS.htm
Oct 16 '05 #8
Richard Grimes wrote:
Arnaud Debaene wrote:
The worst thing however is the IEnumerator interface, which doesn't
allow for insertion, deletion or even *modification* of an item
during enumeration.
Well, I don't see that as a problem. Look at the name of the
interface - it is for *enumerating*. This is interface programming, each
interface
has a behaviour and in the case oif IEnumerable the behaviour is
clear - it gives a serial access to the data in the collection.


I know this is the interface specification.... and what I said is that this
specification is mostly inadequate for no trivial work on a container. But
this is not a problem in itself : The problem is that there is *nothing
else* available ;-)

<...> If you want to change the collection why would you want to use an
interface that enumerates objects in the collection? I understand the
issue you are trying to raise, but the problem is that you are trying
to use the interface to do something that it is specifically not supposed to do.

My point is that there is *no* easy way to modify a container during
enumeration, and that there should be one, because it is quite a common
requirement, and it is quite easy to get it wrong when doing it "by hand"
over and over again. I am not talking about a bug here, but about a lack in
the framework API...

Arnaud
MVP - VC
Oct 16 '05 #9

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

Similar topics

10
by: Mart | last post by:
What class does everyone out there use if they want to store a set of values efficiently? In java I use a HashSet, but there is no equivalent in C#. Even worse, the lowest level interface to...
24
by: Gary van der Merwe | last post by:
Hi When C# 2.0 arrives System.Collections.Specialized.StringCollection will become "obsolete". Will the framework still contain this class, or will there be a C# 1.X to 2.0 conversion utility...
8
by: Arnaud Debaene | last post by:
Hello all, One area where the .Net framework 1.1 is really poor is Collections : We've got very few choice concerning the containers and their characteristics (for example, ArrayList, Queue and...
1
by: Mark Miller | last post by:
I just recently started getting the above error on a page I am posting MULTIPART/FORM-DATA. We have SoftArtisans FileUp component and Filter installed on the server in question and up until a day...
3
by: Rob Thomas | last post by:
Hi, I've been tasked to come up with a new architecture for a large application at one of my customer's sites. In the past, I have developed multi-tier applications whereby the business...
6
by: Ray Cassick \(Home\) | last post by:
Ok, what is up here. The 2005 framework contains all kinds of cool new structures now that we have Generics and all but they always seem to fall just short of exactly what I need. In 2003 I...
3
by: Sharon | last post by:
There is an built-in types table for .NET framework type to C# type which are aliases of predefined types in the System namespace (http://msdn2.microsoft.com/en-US/library/ya5y69ds.aspx). How...
4
by: Ludwig | last post by:
Hi, we're planning to create a framework of reusable components. Now, we are having a discussion on how to set up the namespace hierarchy. We have components like a mult-select TreeView, a...
24
by: luowan | last post by:
Hi I am currently building an application on .NetCF 3.5 in C#. The application needs to process xml files. I am thinking about using LINQ to process XML. I wrote a piece of code to modify the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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,...
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
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...

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.