ArrayList within Custom Control dbnull exception

FreakBoy

Member
Joined
Jul 22, 2006
Messages
15
Location
Near Atlanta
Programming Experience
Beginner
Hi, I'm a fairly inexperienced programmer just working on a project to teach myself some concepts and I've hit a stumbling block I can't find a solution to in any of my books, or a few hours searching through forums and with Google.

I'm replicating a game I've seen before usually called, "Light Game" or something similar. The player is confronted with a grid of "lights" that are either all off or all on and their objective is to reverse this.

By clicking on one of the "lights" the "light" clicked on and all that are adjacent invert.

I spent a lot of time thinking about how to approach the problem and have decided it would be best to redefine a checkbox control that has a Collection property containing references to the adjacent controls.
I've done this so I can have one event handler for every checkbox.

My problem is in the Collection. When I attempt to add anything to the collection (currently an Arraylist) I get a dbnull exception.

I've pulled all of the code back out and tried it without using a custom control and my coding appears to work. Its just that when the collection is used within the control it appears that the collection never becomes anything but "nothing."
 
When you declare an ArrayList variable you are creating a place that an ArrayList can go, but you aren't creating an ArrayList. If you build a garage it doesn't mean that you have a car to drive. This code declares a variable that CAN refer to an ArrayList:
VB.NET:
Dim myArrayList As ArrayList
but there is no ArrayList object. This code declares the variable and then creates an ArrayList object and assigns it to that variable:
VB.NET:
Dim myArrayList As ArrayList

myArrayList = New ArrayList
it is the "New" keyword that invokes the ArrayList constructor which creates the new object. The following are also equivalent:
VB.NET:
Dim myArrayList As ArrayList = New ArrayList
VB.NET:
Dim myArrayList As New ArrayList
 
jmcilhinney said:
it is the "New" keyword that invokes the ArrayList constructor which creates the new object. The following are also equivalent:
VB.NET:
Dim myArrayList As ArrayList = New ArrayList
VB.NET:
Dim myArrayList As New ArrayList

I thought that the code I had was going to handle this...

VB.NET:
Public Class clsCheckBoxNeighbors
    Inherits System.Windows.Forms.CheckBox

    Private myNeighbors As New System.Collections.ArrayList
...
End Class

I'm going to retry it as:


VB.NET:
Public Class clsCheckBoxNeighbors
    Inherits System.Windows.Forms.CheckBox

    Private myNeighbors As System.Collections.ArrayList = New System.Collections.ArrayList
...
End Class

And I'll report back. Thanks for the help!
 
Try creating a separate Collection class that inherits from collection base. By adding the fucntions to add remove etc you will be able to specify a type. Then add an instance of your new collection to your checkbox class..


VB.NET:
Dim Mycollection as new MycollectionClass

Then you can create a property to hold the new collection

Public Readonly Property Items as myCollectionClass
Get
Return Me.MyCollection
End Get
End Property
 
Last edited:
I guess it depends what is the null reference. It may well not be the ArrayList itself, but rather the items you're adding to the ArrayList. It's quite possible to add null references to a collection. When an exception is thrown the debugger shows you the line. You need to break there and test all the references on that line and see which is Nothing.
 
vis781 said:
Try creating a separate Collection class that inherits from collection base. By adding the fucntions to add remove etc you will be able to specify a type. Then add an instance of your new collection to your checkbox class..

Oddly, I started off with a specialized collection class for it. I was getting the same error, so I though that maybe by cutting out possible extra poor-coding problems on my side I could zero in on what was the problem. So right now I have the following:

This is the extra code in the redefined checkbox. I call it "CheckBoxNeighbors" to indicate it is a checkbox that contains a "collection" of references to other checkboxes.

VB.NET:
Public Class clsCheckBoxNeighbors
    Inherits System.Windows.Forms.CheckBox

Private myNeighbors As System.Collections.ArrayList 'The private collection

    Public Property Neighbors() As System.Collections.ArrayList 'The property code for the collection.  I understand that it SHOULD be read only.
        Get
            Return myNeighbors
        End Get
        Set(ByVal Value As System.Collections.ArrayList)
            myNeighbors = Value
        End Set
    End Property

'Here is the Windows Form Designer generated code with my addition in the constructor:
    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()
        'Add any initialization after the InitializeComponent() call
        myNeighbors = New System.Collections.ArrayList ' <-- My Addition Here
    End Sub


I have a specific Sub I've written for testing out the functionality of the checkboxes. Right now all I attempt to do is add a reference of a checkbox to one CheckBox's neighbors list:

"Game" is the form being used, "CB1" and "CB2" are both derived from my new checkbox class.

This code is also where I have the breakdown.

VB.NET:
    Sub PopulateNeighbors()

        Game.CB1.Neighbors.Add(Game.CB2)

    End Sub


On
VB.NET:
 Game.CB1.Neighbors.Add(Game.CB2)

looks like I wrote the wrong error down, it is exactly:

"An unhandled exception of type 'System.NullReferenceException' occurred in LightGame3.exe

Additional Information: Object reference does not set to an instance of an object."
 
Note that you should not have a Setter for your Neighbors property. Properties that expose internal collections should be universally ReadOnly. Why would you want to be able to assign a completely new ArrayList object from outside the class? Because you have a Setter it is possible that a null reference is being assigned after the constructor is executed. Here's how properties like this should be implemented:
VB.NET:
Private _neighbours As Arraylist

Public ReadOnly Property Neighbours() As ArrayList
    Get
        If Me._neighbours Is Nothing Then
            Me._neighbours = New ArrayList
        End If

        Return Me._neighbours
    End Get
End Property
By declaring the property ReadOnly you allow callers to access the collection and add and remove items, but not to assign a new object to the property. By deferring creation of the object until the Getter you make the constructor execute more quickly plus you avoid creating the object at all if it is never used. This way it will be created the first time the property is accessed but not before.
 
I'm going to rewrite the property statement for the colleciton right now. I'll check the references and report back in a moment.

You guys rock.
 
Related question:

The CheckBoxNeighbors control is built to the dll. When I rewrite and then rebuild the control do I need to redo the reference to the custom control? I get the feeling that I don't unless the build's filename changes.
 
What a strange thing to discover once the CheckBoxNeighbors' property had been set to being ReadOnly.

As soon as I did that, when I attempted to build the project using the control, I was given build errors in the original FormDesigner setting for initializing the the form. Each of the custom controls had a line "Me.CBx.Neighbors = Nothing"

A successful build, and a successful execution! Thank you for your help. Its always the tiniest thing!

Thanks thanks!
 
Just wanted to let you all know that everything's working and now I'm doing what I can to figure out if my "game" has a solution. I've created two ways so far of testing, one using random numbers to select a checkbox to click, and another going sequentially through the checkboxes.

So far, not so good. But I wanted to let you know that everything is working PERFECTLY otherwise. Thanks again.
 
Back
Top