Create your own custom Collection Class

In the last tutorial we introduced the concept of Classes in Visual Basic.  As is the norm, the world of software development has turned a simple, elegant concept into an exercise in pseudo intellectualism.   There’s no need to be intimidated in any way shape or form though as, in its simplest form, a Class Module:

  • Allows you to create MethodsSubroutines and Functions within a Class to help you write code once and once only, obeying the DRY Principle of Do Not Repeat Yourself
  • Takes all the good bits from Variables and Arrays to store values using Properties
  • takes all the good bits from Modules to help you organise your code in one neat well defined clearly named unit

Can you remember the exercises we did previously on the Visual Basic Collection Class?  We created a Collection of a library of Visual Basic books, iterated, sortedsearched and removed items from the Collection.   This code worked and it worked well.

In those tutorials we used the Visual Basic Collection Class to store a rather small Collection of books on Visual Basic development.  We chose this particular Class as it is extremely helpful for storing lists of key value pairs.  However a major drawback of this Collection is that it’s impossible to read an item’s key. How can we improve on what’s provided out of the box?

Another potential flaw in our application architecture is where the code to sort and search the Collection resides; it’s embedded in the Form.  This is fine in a one Form application but what happens if we added another Form to the application and this Form wanted to make use of this code?  We could of course use a Module to organise the code.   The Module could be called something relevant to sorting and searching a book Collection – this would have the added bonus of making the code far easier to understand.  However do you remember when I said that a Class Module is like a Module on steroids?  Let me show you how.   Let’s create our own Collection Class which is specifically tailored for our needs, improving on what is provided out of the box.

Open Visual Basic and open the Collection Class Project.

Add new Class to the Project by right clicking on the Project, Click Add in the popup menu and select Class… as shown below:

new class

Call this new Class VBBookCollection.

Open the code Class Module and you’ll see the default code for creating a Class.

Public Class VBBookCollection

End Class

This code declares a Class called VBBookCollection, the Public keyword tells Visual Basic that the Class is accessible anywhere in our application.  We can also use other accessibility levels but we will delve into that deeper in this tutorial.  For now all classes are Public.

If you forgot to set the name when adding the Class the Class will be called Class1.  Don’t worry, just change the name in the code and in the Solution Explorer.

Within this Class, we could use an array to store the Collection of books.  However, as we don’t know how many books I may buy and may want to add and remove at runtime, let’s use the Visual Basic Collection Class.

Public Class VBBookCollection
     Private col As Collection = New Collection
End Class

The more observant among you will have noticed we use the keyword New when creating a CollectionCollection.  Why do we not use this keyword for other Variables?   Classes are known as Complex Types in Visual Basic.  Integers, Strings etc are known as Primitive Types.  For all Complex Types we must explicitly create a new Instance of that type and we create an Instance by saying New.   Complex Types can be memory intensive; we can store lots of information in variables of this type.  To be as efficient as possible with memory, we tell exactly Visual Basic when we want to create the Instance.  In addition, to be uber efficient, we can also instruct Visual Basic when we want to forget the Variable by using the syntax Variable = Nothing.   This instructs Visual Basic to forget the Variable and free the valuable memory.

Back to our Class – we have a local Variable called col which is of type Collection.  This is a Private Variable which means that it’s only accessible from within the Class.  It is not available to our Form.  So how do we manipulate the contents of this Class if it’s Private?  We will create Public Properties and Methods in the VBBookCollection Class to access this Private Collection.

If you look closely at the Form, it makes use of the Visual Basic Collection Class’ Remove Method.  We’ll need one in our Class too.  The VB Collection Class’ Remove Method doesn’t return a value.  Hence we’ll make our own Remove Method a Subroutine.

Add the following code to the Class:

</span></p>

<pre>Public Sub Remove(ByVal isbn as String)
     col.Remove( isbn )
End Sub

The Form also calls the Contains Method of the VB Collection Class to determine if an item exists in the Collection. We’ll need one of these in our Class too.  The VB Collection Class Method returns True or False.  To replicate this functionality we will need to return a True/False value in our Method.  Hence our Contains Method will be a Function of type Boolean.

Add the following code to your Class:

Public Function Contains(ByVal isbn as String) as Boolean
     return col.Contains( isbn )
End Function

Our Form also needs to know the number of items in the Collection.  Add the following Function of type Integer to our Class:

Public Function Count() As Integer
     Return col.Count
End Function

Our Form also expects an Item method, which returns a book in the Collection.

Add the following code to the Class:

Public Function Item(ByVal isbn As String) As String
     Return col.Item(isbn).ToString
End Function

Public Function Item(ByVal index as Integer) as String
     Return col.Item(index).ToString
End Function

That’s right; add two Functions of the same name to the Class.  In our Form we make use of the Item method in two places.   In one case we passed the ISBN of the book, a String value, and the other we passed the numerical index of the book in the Collection.  In Visual Basic .NET we can create Subs and Functions with the same name, as long as the definition of the Sub or Function is different. The more technical term is the signature of the Sub or Function must be different.   In this case, we have passed a key as type String and the Index as type Integer to the two Item Methods.  This is called Method Overloading and is very powerful when used well.   Visual Basic will work out what particular version of the Method to call depending on what you pass to it.   You don’t have to do a thing.  If you pass a String VB will call the Item by ISBN version of the Method.  If you pass an Integer it will call the Index version of the Method.  It makes the code a lot more logical.   The two Functions serve the exact same purpose, to return an Item, so it makes sense that they have the same name.   VB6 didn’t allow Method Overloading.  To work around this we would declare Functions with convoluted and lengthy names like GetItemByIndex and GetItemByISBN.  Method Overloading allows for much more elegant consistent code.

We also need an Add Method.  The Add Method has a number of optional parameters.  In our sample application we have passed the name of the book, the ISBN and sometimes we passed the position to add the book.  To allow this in our own Collection Class, we’ll need to create Optional Parameters.

Public Sub Add(ByVal item As String, ByVal isbn As String, Optional ByVal before As Integer = -1, Optional ByVal after As Integer = -1)
     If before = -1 And after = -1 Then
          col.Add(item, isbn)
     ElseIf before = -1 Then
          col.Add(item, isbn, , after)
     ElseIf after = -1 Then
          col.Add(item, isbn, before)
    End If
End Sub

The code in our Form only passes a before or an after, if one is passed at all.  This method allows for that.

Go back to the code in your Form and replace this declaration for the Visual Basic Collection Class:

Private collectionBooks As New Collection

with this declaration for our new VBBookCollection Class:

Public BookCollection as VBBookCollection

Replace all references to CollectionBooks in the Form with BookCollection.  A quick way to do this is to click on the word CollectionBooks in the declaration, Right Click on your mouse and click Rename.  Another way is to click the Edit Menu, select Find and Replace and click Quick Replace.

What you have done here is create a new Property for the Form called BookCollection.

You’ve worked with Properties before.  Whenever you’ve changed the name of a Form, you’ve changed the Name Property.  Properties are items of data that manipulate the contents of the Class in some way.  A Form in Visual Basic is a type of Class with a number of pre-defined Properties.  Our BookCollection declaration creates a Form Level Variable.  By declaring it Public Variable we have created a Public Property on the Form called BookCollection.  Like all other Form Properties, this Property will be detected by Intellisense and allow all consumers of that Form to set or read that Property.  It is also possible to create Read Only or Write Only Properties which this MSDN article nearly describes.

Add a new Module to your Project called Main.

visual basic project add module

Paste in this code:

Module Main
     Sub Main()
          Dim col As New VBBookCollection
          Dim myForm As New Form1

          Form1.BookCollection = col
          Form1.ShowDialog()
     End Sub
End Module

Here we have created a new instance of the Form and our new VBBookCollection Class, assigning the VBBookCollection Variable to the BookCollection Form Property.  Finally we show the Form as a Dialog.

Typically when we run our Project, Form1 is the first item in the Project to run.  We can change this behaviour so that the Module Main runs by default.

  • Right click on the Solution Explorer
  • Click Properties
  • Clear the “Enable application framework” checkbox in the resulting Form
  • Select Sub Main as the Startup object as shown below:

This instructs Visual Basic to run Sub Main at the start of the Project.

Run the program and, you have, erm, exactly the same results as before.  You’ve created your own Collection Class.

“Big Deal!”, I hear you ask!  It doesn’t do anything different to the one provided out of the box.  However, now we have our own custom Collection Class we can make it do whatever we want.

Read the next tutorial and all will become clear.