Jeff and .NET

The .NET musings of Jeff Putz

Sponsors

News

My Sites

Archives

Are typed ArrayLists a good idea?

I love ArrayLists. I find them to be among the most useful collections in the .NET Framework. I remember seeing a discussion somewhere a few months ago about making ArrayLists into strongly-typed collections. This was achieved by simply inheriting ArrayList and overriding the Add/Insert methods to make sure the objects being added were a particular type.

I don't know enough about what's going on under the hood to know if there's a performance penalty involved with this. Is checking the type of an object an expensive process?
Posted: Dec 24 2004, 02:20 PM by Jeff | with 11 comment(s)
Filed under:

Comments

Frans Bouma said:

Don't worry about that, worry about something else. As soon as you call Add(), the base class, CollectionBase, will first check if the object to add is already in the list. This is a linear search. This means that it calls equals on all already present elements. If an arraylist gets bigger and bigger, this will affect performance way more.
# December 24, 2004 3:31 PM

boogs said:

Heh, they're one of the *only* collections in the .NET framework :).

Typed collections are usually a pretty good idea. They make it so that the compiler can tell you when you accidentally put something in the list that you didn't mean to.

In the next version of the framework, there will be Templates, and you won't need to inherit array list to create strongly typed collections at all. You will wonder how you ever did without.
# December 24, 2004 4:23 PM

Zknet said:

Frans,

Are you sure about that? From looking at Reflector, I don't see any evidence that ArrayList.Add() checks for a duplicate value. Nor does it appear to derive from CollectionBase.
# December 24, 2004 5:08 PM

moonjogger said:

ArrayList does not inherit from CollectionBase - CollectionBase *contains* ArrayList :-)

"Typed ArrayLists" are good idea when you want to be sure that the collection will contain only objects from a specified class and nothing else(checking for null before adding an item is also a good idea)... Always put your business objects in a coresponding typed collection.
# December 24, 2004 5:41 PM

Zknet said:

"ArrayList does not inherit from CollectionBase - CollectionBase *contains* ArrayList."

Maybe I'm missing something, but I don't see that anywhere. CollectionBase and ArrayList both implement IList, which is derived from ICollection. That's the only commonality I see between ArrayList and CollectionBase.
# December 24, 2004 5:53 PM

Wilco B. said:

Zknet: Check the members of CollectionBase. It has a protected 'List' property of the type ArrayList.
# December 24, 2004 6:36 PM

Zknet said:

I see now. List is IList, but InnerList & list are ArrayLists. Missed those before. Thanks.
# December 24, 2004 8:46 PM

.Net Adventures said:

ArrayList in C# is designed with reference types in mind.Using ArrayList with value types leads to unnecessary boxing and unboxing, which degrades performance.
# December 25, 2004 5:36 AM

Drew Marsh said:

Yeah, I'm not sure I understand where Frans is coming from on this. Here's the IL for CollectionBase.Add (see below). No where in the scope of this method (or any of the OnXXX calls made) is there a scan of the contained ArrayList to check if the instance of the object being added is already in the list.

<codeSnippet language="MSIL">
.method private hidebysig newslot virtual final
instance int32 System.Collections.IList.Add(object 'value') cil managed
{
.override System.Collections.IList::Add
// Code size 65 (0x41)
.maxstack 3
.locals (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: callvirt instance void System.Collections.CollectionBase::OnValidate(object)
IL_0007: ldarg.0
IL_0008: ldarg.0
IL_0009: call instance class System.Collections.ArrayList System.Collections.CollectionBase::get_InnerList()
IL_000e: callvirt instance int32 System.Collections.ArrayList::get_Count()
IL_0013: ldarg.1
IL_0014: callvirt instance void System.Collections.CollectionBase::OnInsert(int32,
object)
IL_0019: ldarg.0
IL_001a: call instance class System.Collections.ArrayList System.Collections.CollectionBase::get_InnerList()
IL_001f: ldarg.1
IL_0020: callvirt instance int32 System.Collections.ArrayList::Add(object)
IL_0025: stloc.0
.try
{
IL_0026: ldarg.0
IL_0027: ldloc.0
IL_0028: ldarg.1
IL_0029: callvirt instance void System.Collections.CollectionBase::OnInsertComplete(int32,
object)
IL_002e: leave.s IL_003f
} // end .try
catch System.Exception
{
IL_0030: pop
IL_0031: ldarg.0
IL_0032: call instance class System.Collections.ArrayList System.Collections.CollectionBase::get_InnerList()
IL_0037: ldloc.0
IL_0038: callvirt instance void System.Collections.ArrayList::RemoveAt(int32)
IL_003d: rethrow
} // end handler
IL_003f: ldloc.0
IL_0040: ret
} // end of method CollectionBase::System.Collections.IList.Add
</codeSnippet>
# December 25, 2004 12:53 PM

pottman said:

I am coming to this discussion late but wanted to chime in. I recently rolled off a project where I spent six months in the role of performance engineer on an enterprise .net project. This very argument raged on for weeks before I created a test application which created several different collection implementations, including typed collections, and cycled through them several million times. It's been a while so some of the details are lost, but the most startling thing was that the ArrayList, in any capacity, was in that small group that had great performance. In reference to the boxing, this brings the performance of any collection to its knees. This is an incredibly easy test to put together, and I would welcome any feedback from the readers of this blog as I still consult on performance. I agree that when you know the type, typed collections are the way to go, but overall, the ArrayList is one that i too have come to love in the .net framework.
# January 12, 2005 9:37 AM

nekit said:

to pottman:
Did you have Templates i your performance test? I would be curious to compare Typed ArrayList and Templated collection performace. Did anyone hear about such tests?
# January 20, 2005 1:14 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)