Introduction to Custom Collection Classes, the CollectionBase
Since starting with .NET back in the summer of 2001 I have used datasets and dataviews about 99.9% of the time to organize my records of data for my applications. I think they are great, especially the dataview. I mean you can execute SQL right inside of your view with the RowFilter and Sort commands. I have thought many times about using custom collections to hold set of records for some of my applications. Unfortunately I typically had deadlines that were too tight to experiment a little.
I decided to change that a little over the weekend. I went back and spent a little time reviewing the fundamentals of the collection classes a few days ago to see if it was something to pursue. There are several considerations I had in order to decide what I needed to do. First would it be too much of a burden on the application to process the data. I generally develop web sites, so speed is truly of the essence when serving a web page. My thinking at this point is that there are relatively few records I need to hold, at least in my initial implementations and I think it will not be an issue for me. Also on the same note, instead of having a dataset with all of its overhead in memory for just 3-20 records, this too might be an improvement. Finally the routine to fill my collection would use a SQLDataReader, which is by nature extremely fast way to retrieve data from the database.
So with all that evaluation, I decided to go forward with my plan. The first application I wanted to try this on has an object, we will call it a Customer. The Customer Object has your normal properties for things like name, address, etc. Where the collection classes can come in real handy is storing multiple addresses, phone numbers, orders and any other sort of item that there may have multiple items associated with it.
The next step for me was to create a CodeSmith template to consistently create my collection classes. I decided to modify by business layer template to have it create my collection class for me each time. There is nothing fancy about my collection class, it is derived from CollectionBase, which gives it a lot of core functionality. It has standard methods for Add, Remove, IndexOf, Replace, Contains (glad Microsoft put this in the String Class), and Item. There are event handlers for Insert, Remove, Set and Validate.
The nice thing about using a collection class is now I can add more methods to return specific information. For example a ShoppingCartCollection class might have a property call OrderTotal, Shipping and GrandTotal. These methods could return collective values based on the items in the collection. Let's look at an example for OrderTotal. It would take the quantity and retail price for each item, sum that up and then subtract any discounts that may apply.
Public Function OrderTotal() as decimal
dim dTotal as decimal = 0For i = 0 To list.Count - 1Dim tempCI As ShoppingCartInfo = CType(list.Item(i), ShoppingCartInfo)
dTotal += tempCI.Qty * (tempCI.Retail - tempCI.Discount)
This is a simplified example, but you can get the idea as to how powerful this can be. This idea can be extended to our CustomerInfo class too. Now we can define properties to give us some useful data for a customer pretty quick. We could create a method to get a specific item, like a home address from the address collection, or a summary value, like total amount ordered.''' <summary>''' ''' </summary>''' <returns>The Home AddressInfo if it exists</returns>''' <remarks></remarks>Public Function GetHomeAddress() As AddressInfoReturn GetAddressByType(AddressType.Home)End FunctionPublic Function GetAddressByType(ByVal AddressTypeID As Integer) As AddressInfoDim i As IntegerFor i = 0 To List.Count - 1Dim ai As AddressInfo = CType(List.Item(i), AddressInfo)If ai.AddressTypeID = AddressTypeID ThenReturn aiEnd IfNextReturn NothingEnd Function
So initially the use of custom collections looks to be beneficial to developing applications. The speed impact for an application is negligable, the ability to quickly access information if obvious and I think going forward the code should be easier to maintain. In my next entry on custom collection classes we will examine the ability to bind the collections to dataview, datagrids and datalist. A little hint, it worked better than I thought.