Flylib.com

Books Software

 
 
 

3.16 Create a Strongly Typed Collection


3.16 Create a Strongly Typed Collection

Problem

You need to create a collection that can only contain one type of object and rejects attempts to add other data types.

Solution

Create a custom collection class by deriving from System.Collections.CollectionBase , and implement type-safe Add , Remove , and Item methods .

Discussion

You could create a custom collection by implementing the IList , ICollection , and IEnumerable interfaces. However, .NET provides an easier option with the abstract CollectionBase class. Internally, the CollectionBase uses an ArrayList , which is exposed through the protected property List .

As an example, consider the simple Customer object shown here:

Public Class Customer Private _ID As Integer Private _FirstName As String Private _LastName As String Public Sub New(ByVal id As Integer, ByVal firstName As String, _ ByVal lastName As String) Me.ID = id Me.FirstName = firstName Me.LastName = lastName End Sub Public Property ID() As Integer Get Return Me._ID End Get Set(ByVal Value As Integer) Me._ID = Value End Set End Property Public Property FirstName() As String Get Return Me._FirstName End Get Set(ByVal Value As String) Me._FirstName = Value End Set End Property Public Property LastName() As String Get Return Me._LastName End Get Set(ByVal Value As String) Me._LastName = Value End Set End Property End Class

You can derive a type-safe CustomerCollection from CollectionBase . Then you add a strongly typed Add method and a default property named Item , which automatically casts the retrieved object to the correct type.

Public Class CustomerCollection Inherits System.Collections.CollectionBase Public Sub Add(ByVal item As Customer) Me.List.Add(item) End Sub Public Sub Remove(ByVal index As Integer) If index > Count - 1 Or index < 0 Then Throw New ArgumentOutOfRangeException( _ "No item at the specified index.") Else List.RemoveAt(index) End If End Sub Default Public Property Item(ByVal index As Integer) As Customer Get Return CType(Me.List.Item(index), Customer) End Get Set(ByVal Value As Customer) Me.List.Item(index) = Value End Set End Property End Class

Here's a simple test of the type-safe CustomerCollection :

Dim Customers As New CustomerCollection() ' This succeeds. Customers.Add(New Customer(1001, "Henry", "Bloge")) ' This fails at compile time. Customers.Add("This is a string")

One limitation of the CollectionBase approach is that you can only create nonkeyed collections (such as the ArrayList ). If you need to create a strongly typed dictionary collection, see recipe 3.17.

Incidentally, the .NET Framework includes one strongly typed collection class: the StringCollection class in the System.Collections.Specialized namespace, which only allows String objects.



3.17 Create a Strongly Typed Dictionary Collection

Problem

You need to create a key-based collection that can only contain one type of object and rejects attempts to add other data types.

Solution

Create a custom dictionary collection class by deriving from System.Collections.DictionaryBase , and implement type-safe Add , Remove , and Item methods .

Discussion

With a custom dictionary collection, you can place restrictions on the type of objects stored in the collection and on the type of object used to index items in the collection. Internally, the DictionaryBase object uses an ordinary weakly typed Hashtable , which is exposed through the protected property Dictionary . However, external code can't directly access this collection. Instead, it must use one of the type-safe methods you add to your custom class.

As an example, consider the simple Customer object shown in recipe 3.16. Using DictionaryBase , you can derive a type-safe CustomerDictionary that has a strongly typed Add method, which requires an integer key and only accepts Customer objects for insertion in a collection. You'll also implement a Remove method and a default property named Item , which automatically casts the retrieved object to the correct type.

Public Class CustomerDictionary Inherits System.Collections.DictionaryBase Public Sub Add(ByVal key As Integer, ByVal item As Customer) Me.Dictionary.Add(key, item) End Sub Public Sub Remove(ByVal key As Integer) Me.Dictionary.Remove(key) End Sub Default Public Property Item(ByVal key As Integer) As Customer Get Return CType(Me.Dictionary.Item(key), Customer) End Get Set(ByVal value As Customer) Me.Dictionary.Item(key) = value End Set End Property End Class

Here's a simple test of the type-safe CustomerDictionary :

Dim Customers As New CustomerDictionary() Dim CustomerA As New Customer(1001, "Henry", "Bloge") ' This succeeds. Customers.Add(CustomerA.ID, CustomerA) ' This fails because the object is not a Customer. Customers.Add(9024, "This is a string") ' This fails because the ID is not an integer. Customers.Add(CustomerA.FirstName, CustomerA)

Incidentally, the .NET Framework includes one strongly typed dictionary class: the StringDictionary class in the System.Collections.Specialized namespace, which only allows String objects.