The reason why Collection, ReadOnlyCollection, and KeyedCollection were moved to System.Collections.ObjectModel namespace

Several people asked me why Collection<T>, ReadOnlyCollection<T>, and KeyedCollection<TKey,TValue> were moved to System.Collections.ObjectModel namespace. Here are the two main reasons:

1.      Microsoft.VisualBasic namespace contains a non-generic type called Collection. The namespace is imported by default by the VB project template and we were afraid that it would confuse developers who import System.Collections.Generic namespace as well and would see two types called ‘Collection’ in their intellisense (given one of them generic, but still). We were faced with either renaming Collection<T> to something else or moving it to another namespace. We really did not want to rename it because Collection<T> is just the best name for the type (with not many good alternatives) and it will show in many APIs.

2.      We also thought that not many people will need to declare variables of thses types. Most developer who will directly use (instantiate) the collections are framework (object model) designers. Developers writing applications (majority) would simply call Directory.Files.Count for example (and not even realize it’s a Collection<FilerInfo>) or they will/should use List<T> instead. Having said that, recently I started to be concerned that some people will have to declare Collection<X> variables to cache collection instances they get from APIs, but I have not received any substantial feedback on this. BTW, this will be mitigated by many APIs actually returning subclasses of Collection<X> instead of the base class.

Some people also commented that the name “ObjectModel” is a bit “kooky” (direct quote). I have received some feedback (not much but some) about it from customers, but I think the main issue is that the term is so overloaded and many people mean many different things when they say “object model”. Anyway, we would probably try to come up with some less controversial name if we were in the design phase today, but it’s kind of late in the product cycle now to make such changes.

Comments (32)

  1. I think you should put them back into the System.Collections namespace and suffix each type with ‘base’. e.g. CollectionBase<T>

  2. Seems to me that you are guaranteeing that Collection<T> et al will end up in a backwater.

    Im not sure that the needs of intellisense should drive any decisions about how to structure namespaces.

    That said, if you were going to jigger the namespaces to push these classes into the background, may i suggest System.Collections.Generic.Fundamental

  3. Keith Hill says:

    Since VB doesn’t import System.Collections.Generic by default I guess I would just leave these types in System.Collections.Generic. I cringe when I hear folks make "unusual" API design choices just to accomodate Intellisense. Ew.

    OK I just tried this in the FebCTP bits. If you manually import System.Collections.ObjectModel you get this in the Intellisense list:


    Collection(Of T)

    That doesn’t seem confusing to me at all. Just put ’em back where they belong. 🙂

  4. AndrewSeven says:

    Please stop punishing the rest of us for things that you assume VB people won’t understand.

  5. We don’t want to suffix them with "Base" because they will often show in APIs and it’s slightly worse to see

    public CollectionBase<FileInfo> Files { get;}

    … than

    public Collection<FileInfo> Files { get;}.

    I do agree with the sentiment that seeing both Collection and Collection(of T) in intellisense is not bad (and I will pass this feedback to the VB team). I would presonally prefer the collection in the main namesapce myself, but I did get strong feedback from the VB team that it is a problem for many people.

    Thirdly, I have to say that I disagree that intellisense should not influence API design. Modern development platforms are APIs + Tools. They are not seperable. You need to design them together. Of course, knowing when to change APIs and when to fix tools is an important consideration. In this particular case we decided that changing the API was net better than changing the tools.

  6. Well here in lies the conundrum. When you put it into a namespace like ‘ObjectModel’ you iply it’s going to be used in someones object model. So consider a User object in a ECC design pattern style object model. You would have User, UserCollection and UserFactory. You would not have User, Collection<User>, UserFactory.

    I would mark it abstract, teach people how to inherit ala

    public class UserCollection : Collection<User>


    and drive good design. Let’s face it, in an ‘ObjectModel’ you would strong type directly (even if it’s a simple like above).

    When you consume ala Collection<User> the collection is not part of the same object model as the User (my OM). It is part of your OM and I am a consumer.

    Sometimes you people really make me wonder. Are you seriously going to muck up the netFx BCL to support backwards compat with a VB6 object?

    If you ask me you should either put it back and deprecate the VB object, or mark it abstract and force people to use it via inheritiance in ‘thier’ object model.

    This is just dumb…

  7. Paul Vick says:

    In Beta2, we will be adding the default import of System.Collections.Generic to VB – for some reason it didn’t make it into Beta1. So this will be an issue.

    And Krzysztof makes it sound like we think that VB users would be scared simply by the fact that they saw a generic and non-generic type together. This is incorrect and misleading. The issue is not that you’ll see "Collection" and "Collection(Of T)", but that the two types are *radically different*. The naming implies that the latter is just a generic version of the former, but nothing could be further than the truth. There are many, many behavioral differences between the two types, some of them extremely subtle.

    The point is just that whether you are a VB developer, C# developer or a C++ developer (or, hell, an Eiffel developer), seeing two types with the same name overloaded on arity implies that the types have some passing relationship to each other and that one can move to a more strongly typed world simply by adding "<x>" or "(Of x)". This violates that simple principle pretty heavily.

    In fact, the *CLR itself* has cited just this issue as one of the reasons why we have ArrayList and List(Of T) instead of ArrayList and ArrayList(Of T). Frankly, what’s good for the goose is good for the gander.

  8. Keith Hill says:

    Well pushing Collection(Of T) into ObjectModel isn’t going to really solve the problem is it. VB programmers will see that someone’s API returns a Collection(Of Foo) (programmer was lazy and didn’t derive from the type but used it directly) and by your reckoning, they will be confused because the generic version is much more rich than the VB collection. OK I can believe that. 🙂 Seems like to me the VB folks would really prefer that you rename Collection(Of T) to something else. Perhaps Paul Murphy has it right – mark them abstract. Then name them Collection*Base(Of T) and put them back in System.Collections.Generic.

  9. How are we support sort a collection that is derived from Collection(Of t)? Since Me.InnerList doesn’t exist in Collection(Of t)?

  10. I think Paul is correct here. Vb already has the Type Collection, and it woudl make sense in the future if that was Collection&lt;T&gt;, whihc would indicate a type whereh the items are strongly typed and accessible by both index adn key.
    <br>ObjectModel.Colleciton&lt;T&gt; on the other hand seems to be nothign more than a class that attemtps to encapsualte List&lt;T&gt;, yet does so rather poorly as it still exposes a reference to the lists via the Items property.
    <br>Seriously I find myself asking why even have ObjectModel.Collection&lt;T&gt; when we have List&lt;T&gt;. Andto name it so as the only thing preventing a clash with a generic from of the Vb Colleciton class is by having to use namespaces, seems really silly.

  11. scratch that last bit about not seeing the reasong for ObjectModel.Collection(Of T).. I thought Items was public, not protected. So that changes things a lot 😉
    <br>Still, on the other point, the potential clash with a VB Colelction class that is generic is still problematic and a rename would have been more suitable, perhaps something like SimpleList would have been more appropiate and be more self describing too when looking at the plethera of list/colleciton types to choose

  12. Daniel Moth says:

    Blog link of the week 11

  13. Eric Newton says:

    I have to agree with "Paul D. Murphy". You’re about to make another poor namespace decision because of VB6, and make all of us (a number of consumers that should be GROWING at a much more substantial pace than VB6)

    Not to mention that VB6 people STILL don’t use VB.Net… Why? because they like (*REALLY LIKE*)/understand/don’t-wanna-learn-OO-VB VB6.

    Why don’t you focus more on Education and documentation. For instance, push the responsibility onto the VB team. When intellisense comes up, are ya gonna show the "OLD" Microsoft.VisualBasic.Collections (which STILL use 1 based numbering) in the list? That’s fine, just give the people who know "VB.NET" the correct option of System.Collections.Collection (hmmm, did the VB6 people get confused with the two "Collection" names in the namespace?)

    I urge you to reconsider such a silly idea. I urge the VB team to step up and consider modifying intellisense to cater to BOTH crowds that you continue to coddle. (IMO, the VB.Net crowd SHOULD be who you’re focusing on, since they are obviously more forward thinking than the people that still start new projects in VB6 "because they dont wanna learn OO-VB")

  14. Thong Nguyen says:

    This is the lamest thing I’ve every heard. Could Microsoft design worse APIs? Why can Microsoft create such great runtimes but such crappy APIs?

    Collection is NOT the sensible name for a class that implements ICollection *AND* IList. ListCollection is the right name.

    Either do that or redefine ICollection and IList.

    As ICollection clearly defines; ICollection is a generic definition of an interface for an object that "holds" something in some way. It does not define the additional features an object implemeting IList would. You think Collection is the best name for an object that implements ICollection *AND* IList? I don’t understand why you just didn’t call the class "Thing".

    Why can Sun get OOP but not Microsoft?

    I recommend Microsoft programmers have a look at Java’s collection classes and marvel at their beauty. The names "List" and "Collection" used for concrete classes in the beta2 BCL makes me shudder.

    List and Collections are *abstract* concepts. LinkedList, ArrayList and HashMap, TreeMap, etc are concrete concepts. Any first year algorithms student knows this…..

  15. Emil says:

    You could just rename "ObjectModel" to "BaseClasses" since the ObjectModel just contains abstract base classes for other classes to inherit from.

  16. Majority of ObjectModel collections are not abstract and in fact are often used directly.

  17. David Nelson says:

    I have to say that this was a truly terrible idea, for a number of reasons:

    1. "Modern development platforms are APIs + Tools. They are not seperable. You need to design them together."

    Yet another example of Microsoft’s astonishing arrogance. Are you implying that the only way to write .NET code is to use Visual Studio? Because, guess what, its not. Design tools are an essential part of a modern development environment, yes; but the framework should be built to stand the test of ANY environment, and the specific tools which are built ON TOP OF (not alongside) that framework should conform to the framework.

    2. Please, please, PLEASE stop assuming that all Visual Basic programmers are stupid. If they don’t know enough about the environment they are working in to know the difference between VisualBasic’s Collection and the framework’s Collection<>, that is what the MSDN is for; they can go look it up. Relegating an otherwise useful collection to a backwater namespace where no one can find it because you are afraid that a small subset of users is going to get confused is what happens when marketing people start making programming decisions.

    3. If you are afraid that people might think the two classes are related when in fact they are not, maybe that should tell you that one (or both) of the classes are misnamed. In fact, Collection<> was a horrible choice for that class. "Collection" is a general term for a structure which holds things; hence the interfaces ICollection and ICollection<>. Collection<> is actually a list; in fact, the only different between Collection<> and List<> is that Collection<> has some overridable methods for taking specific actions when the list changes. That makes Collection<> a MORE specific version of List<>, and yet it was given a LESS specific name. How did this make it out of the first round of design? Surely even the interns at Microsoft could have figured this one out? And if you were so worried about name confusion, why does the vast difference between the similarly named ICollection<> and Collection<>?

    I love .NET, but I am too often confounded by the obviously terrible decisions that are made by the designers (witness the forth-coming collection intializers in C# 3.0). At the very least Microsoft needs to spend more time getting community feedback on design issues in earlier stages, so that we can point out the obvious flaws before it is too late to correct them.

  18. David,

    Thanks for your perspective.

    “Are you implying that the only way to write .NET code is to use Visual Studio?”

    No. First, we build roads because many people use cars and cars drive better on roads. The fact that we build roads does not imply that cars are the only means of transportation. Secondly, Intellisense is common in many code editors these days.

    “Please, please, PLEASE stop assuming that all Visual Basic programmers are stupid.”

    I don’t think all VB programmers are stupid. Please don’t imply that I do :-). As to the main point, I hope you are not arguing that we can make APIs arbitrarily confusing and expect that MSDN will straighten it all out. If you are just pointing out that we made a bad trade off in this case, then point taken. And, no marketing person was involved in making this decision.

    Could you suggest a better name for Collection<T>? We wanted a name that is short and works well in the main scenario: the type of properties. In such scenarios, the user does not care much about anything besides that the property represents a collection of something.

  19. Dave Lessard says:

    I know I’m late in here but how is the new Collection(Of T) better than CollectionBase?  There are no protected overridable methods like OnInsertComplete.  How do you write a base collection class and not include methods to hook events on for something like ObjectAdded or ObjectRemoved?  

    These are the basic constructs that make working with collections usable.  I have noticed that in .NET 3.0 there is an ObservableCollection that I wish was in .NET 2.0.  

    Generics are such a great feature to 2.0, I just wish I could use something in the framework that makes sense on collections.  

    Collection(Of T) doesn’t even have overridable Add(), or Remove() methods that you could hook your own events to.  Instead I have to use the cheesy Shadows keyword (or new in c#).  

    Seems CollectionBase has more flexibiliy although when I extend it in a generic derived collection, it no longer works with the "Show As Collection Association" in the Class Diagram.

  20. Dave, you should take a look at the following MSDN topic on Collection<T>:

    It shows how to override protected APIs to hook up events.

  21. Dave Lessard says:

    That’s fine, but having a base class to do it is the whole point to me.  Bacially I might as well write my own implementation of IList(Of T) if I have to override and the functionality of Collection(Of T) anyway.  I just need to make sure I implement them correct, which saves no time.  

    I’ll look forward to ObservableCollection in 3.0.  For now I’ll stick with CollectionBase.


  22. Dave, I don’t understand how is it different from CollectionBase. You have to do exactly the same with CollectionBase. In addition, when you inherit from CB you need to provide strongly typed accessors. Also, CB will box value types, but Collection<T> won’t. Collection<T> is basically superior CB.

  23. Dave Lessard says:

    It’s better because I am fairly certain that the .NET team implemented the OnInsertComplete and OnRemoveComplete methods correctly and I can capture these methods and raise my own events.  With Collection<T> I have to make sure my implementation is working at every entry point on Add(), Remove(), AddRange(), RemoveAt(), I have to override every method with my own implementation or any other method I might add to the collection, which costs time in testing.

    I can also just extend CollectionBase with my own Generic abstract class which takes care of the type, I would have to override Collection<T>’s methods anyway.  The biggest point is whatever method an object gets added or removed from the collection I can count on getting notified by the protected methods and not have to worry about my implementation doing it correctly.  To me the most usefull thing in collections is managing and notifying when objects are added or removed, all collections have the basic enumeration methods, any custom Get() methods have to be added regardless.  Updating UI list components with underlying domain objects is my main use.

  24. Peter.O says:

    Any time I get involved in discussions about why irreconsiliable stuff had to be done to accommodate VB users, I wonder which VB users Microsoft talks to. In the 90’s I needed a quick-to-learn programming language to do my research (I was working then as a PhD in medical research). I learnt VB. Within 2 years of getting into the groove of this stuff, I loved it but felt ashamed of myself. First, over 10% of the really powerful stuff could not be done with Microsoft VB. Meanwhile, many 3rd party folks made a living out of providing those same capabilities (as VB plugins) for a fee.

    Then, the coder community would constantly derride the VB world as not really …. bla! bla! It was an admirable language but I had to hate it because it does not help your self esteem for your language of choice to be talked down at like that.

    I don’t blame the c++ or the java communities for this. I blame Microsoft. Microsoft created VB as programming for dummies. And even now that equally smart people are doing VB, that sentiment about even in design choices. O! we have to do so and so because the VB people can’t wrap their head around it!! That’s a shame.

    It was so hard dealing introducing zero indexing to VB.NET and so ensued the option_base sentiments of 2000/2001. But daily, head spinning stuff get added to C# and it’s understood that it won’t be a problem.

    Since then, I have gone to school to do an advanced degree in Computer Science and majored in Programming Languages. I was hoping to find out the reason why VB could not do most of the things C++ could. I found none. And I challenge anyone who to a one-on-one forum. The only restriction was: How much can we add to this language and "confuse the target audience, seeing as they are dummies".

    Now, I fluently write many languages from C to java, from c# to prolog. I am currently playing with F#. I am at the right place to take a wide angle look at all these and come to the conclusion that only VB has been so dasterdly disrespected and that is a political problem that Microsoft has festered on the percieved professional competence of the VB developer.

    I am senior architect at a major IT firm and I hire developers. I write C# for a living because of its textual elegance. But even if VB.NET had textual elegance, I would think twice because that name is sine qua non with "language for dummies".

    It aches my heart when we have to offer a lower compensation package to VB developers compared to their C# counterparts.

    The common language infrastructure initiative is predicated on the ideals of "what one language can do, another language also can". That should be the ‘independence of the VB developer from his stigma’. But Microsoft is so entrenched in this VB philosophy for so long that it’s now so unstoppable that everything else, including even the otherwise elegant .NET BCL has to be polluted into alignment and dummied down to the level of comprehension of the VB developer who can’t understand intellisense.

    As an aside, the problem with designing API and tool together is that you make basic assumptions as to the creativity of the users of the tool. No other field does this so brazenly. Users of ReSharper will find this excuse so laughable! because it automatically offer imports of type namespaces when the type is used. So, the Microsoft argument will have to fail if all namespaces where one continuum of automatically injected namespace in the fluid world of ReSharper. That’s just one example.

    What I would do is to make the API elegant, intuitive and obey the rules. Then make the tool follow closely behind.

  25. Peter, I appreciate your high level message/point. I do agree that we sometimes forget how powerful VB become with the move to .NET and we keep treating it as a RAD only tool, and it is not only that anymore.

    Having said that, the decision to shield the VB developers from Collection<T> is unrelated to this issue. We would do the same if C# had a preexisting collection that had a very similar name but had nothing to do with the generic collection. In fact we do it all the time when we design the Framework. That is, we are very careful to avoid having two types with the same name differing only in the generic parameters, unless the types are very closely related.

  26. Pita.O says:

    Alright Krzysztof, let’s go on an exploratory journey through the BCL as seen in C#.

    The following Timer classes are even exactly the same name but a namespace separation is sufficient to indicate that they are different. And indeed, they are different. Very different!



    System.Collections already has CollectionBase. I would have supported calling the generic version CollectionBase<T> as well, except that ClassBase seems to be a convention I’ll like to reserve for abstract base classes.

    What does VB collection do that will be so difficult to deprecate, anyway? The only difference I see b/w the Microsoft.VisualBasic.Collection and the System.Collection.Generics.ObjectModel.Collection is that the VB collection can insert an object between two other objects.  If this is so important, implement it in the System.Collections namespace and make Collection<T> to also do it. If you ask me, a VB Collection is nearly like ArrayList. Retaining the name made sense for automatically migrating VB code in .NET 1.0 and 1.1.  Any further than that, it begins to be excess luggage like C++ inherited from C, stifling its evolution.

    In practice, VB migration to VB.NET has no real turn-key solution. Most of the old code requires redesign, anyway!

  27. DevTopics says:

    If you need a collection of objects accessed by a key, and the key is one of the object’s properties, then you should use the KeyedCollection class instead of Dictionary.

  28. Ben says:

    OK, so I’m a bit late. But I so totally agree with Thong Nguyen (April 1, 2005 7:08 AM) that I had to express my support for what he says…

    "This is the lamest thing I’ve every heard. Could Microsoft design worse APIs?"

    "Collection is NOT the sensible name for a class that implements ICollection *AND* IList. ListCollection is the right name.

    Either do that or redefine ICollection and IList. "

    "List and Collections are *abstract* concepts. LinkedList, ArrayList and HashMap, TreeMap, etc are concrete concepts."

    Collection<> actually being an IList<>, and List<> actually being logically a vector/ArrayList, have both tripped me up. I’m sure I’m not the only one.

    Please, naming is one of the most important things to get right in an API.