No Virtual Members on Generic Collections [Ryan Byington]

A customer asked me why we decided to make the members on our generic collection non virtual when every member on the non generic collections was virtual. I though other might be interested in this so I decided to answer it here.


When we shipped the first version of the .NET Framework we wanted to make the collections as flexible as possible by making every method and property on the collections virtual. Allowing users to inherit from our collection and provide new functionality by overriding these members. However this comes at a price since virtual methods are slower then non-virtual methods and virtual methods can not be inlined.


 We received a lot of feedback that the performance of our collections was poor. So in V2.0 when designing the generic collections we decided to make the trade off of speed over flexibility and made the call to make all methods non-virtual.

Comments (5)

  1. davkean says:

    Although, I know you are talking about the base collections, such as List<T>, you might want to clarify that although the Add/Insert, Remove, Clear and indexer aren’t virtual on Collection<T>, they do call virtual members InsertItem, RemoveItem, ClearItems and SetItem respectively.

  2. At the risk of sounding stupid, would it be possible to syndicate the entire article via RSS rather than just the abstract. I cannot read your feed offline now.

  3. IDisposable says:

    +1 on the publishing of the entire article instead of an excerpt!

  4. Kevin Westhead says:

    A problem I’ve experienced with the non-generic collections, separate from performance, was that having all of the members virtual actually caused problems in some scenarios. Consider ArrayList as an example. If I wanted to derive from ArrayList and have my derived collection react in some way whenever a new item was added or an existing item was removed, what methods would I override? For adding, I guess I should consider the following: Add, AddRange, Insert and InsertRange. For removing: Remove, RemoveAt and RemoveRange. However, if I simply override all of these I’ll notice something odd, because AddRange calls InsertRange and Remove calls RemoveAt. I could choose to not bother overriding AddRange or Remove, but can I be sure that the implementation of ArrayList will always work this way? So by having everything virtual I think it actually makes it harder to do a good job of specialising the non-generic collections, and some of them have leaked implementation details into their public APIs.

  5. Instead of deriving from ArrayList, I believe that "CollectionBase" is the preferred 1.1 base class. It as OnXyz pseudo-events that you can override to respond to list change events.

Skip to main content