Class properties and ArrayList

TyB

Well-known member
Joined
May 14, 2009
Messages
102
Programming Experience
3-5
Here's a tricky one and maybe not the best way to do this so I'm open to suggestions.

I have a class with properties. One of the properties is of type ArrayList like so.....

Property DepartmentList() As ArrayList
Get
Return mcolDeptList
End Get
Set(ByVal value As ArrayList)
mcolDeptList = value
End Set
End Property

Ok so now I have a list of Departments in a DB table that I want to put into this property. This is what I'm doing......

............DB Code to get the departments

Dim objDepartment As clsDepartments
objDepartment = New clsDepartments

Dim arrList As New ArrayList

Do While objdatareader.Read
arrList.Add(objdatareader("name"))
Loop

'Add the new array object to the class.
objDepartment.DepartmentList.AddRange(arrList)'ERROR HERE

I am getting an error that I have not set the instance of an object and to use the "New" keyword. I cannot see how to use the new keyword on the class property.

Any help would be apperciated.

Ty
 
Wouldn't you just need to define objDepartment like this...

Dim objDepartment As New clsDepartments
 
If you're using .NET 2.0 or later then you shouldn't be using the ArrayList class at all. Your property should look like this:
VB.NET:
Private _departmentList As New List(Of String)

Public ReadOnly Property DepartmentList() As List(Of String)
    Get
        Return Me._departmentList
    End Get
End Property
or like this if you want lazy-loading:
VB.NET:
Private _departmentList As List(Of String)

Public ReadOnly Property DepartmentList() As List(Of String)
    Get
        If Me._departmentList Is Nothing Then
            Me._departmentList = New List(Of String)
        End If

        Return Me._departmentList
    End Get
End Property
Now loading the data into that list would look like this:
VB.NET:
While reader.Read()
    dept.DepartmentList.Add(CStr(reader("Name")))
End While
or like this if you want to use AddRange:
VB.NET:
Dim names As New List(Of String)

While reader.Read()
    names.Add(CStr(reader("Name")))
End While

dept.DepartmentList.AddRange(names)
 
Still getting same error. I changed the code like so.

Property DepartmentList() As List(Of String)
Get
Return mcolDeptList
End Get
Set(ByVal value As List(Of String))
mcolDeptList = value
End Set
End Property

Dim objDepartment As New clsDepartments

Dim strList As New List(Of String)

Do While objdatareader.Read
strList.Add(objdatareader("name"))
Loop

'Add the new array object to the class.
objDepartment.DepartmentList.AddRange(strList)

Thanks,
Ty
 
You haven't done as I suggested. Your code has a read-write property for one thing, and mine is read-only. The real issue though, is the fact that in my code I create a List and assign it to the field backing the property, which you must not be doing to get that error message. If you do it the way I demonstrated it will work.
 
The property needs to be read/write.

The only difference in what you wrote and what I wrote was your usage of the "Me." keyword which I just tried and did not make a difference.

Thanks,
Ty
 
The property needs to be read/write
Why? Is the Items property of a ComboBox read/write? Is the Rows property of a DataTable read/write? Etc.
The only difference in what you wrote and what I wrote was your usage of the "Me." keyword which I just tried and did not make a difference.
No, there is another very important difference.

I think that you think that the property needs to be read/write because you need to be able to add items to the collection, but adding items to the collection is NOT setting the property. When you add items to the collection you are GETting the property value, i.e. the collection, and then calling a method of that object, e.g. Add or AddRange. At no point are you SETting the property value. Have a look at your own code:
VB.NET:
'Add the new array object to the class.
objDepartment.DepartmentList.AddRange(strList)
You aren't setting the property. You're getting the property and then calling AddRange on the object it returns. Actually seting the property would look like this:
VB.NET:
'Add the new array object to the class.
objDepartment.DepartmentList = strList
but that is NOT the way to expose collections via properties.

The crucial difference between my code and yours, and the reson you're getting a NullReferenceException, is that you are trying to get the collection object from the property and then call its AddRange method but you haven't created the collection object in the first place. Here's the crucial part in my code:
VB.NET:
Private _departmentList As [B][U][COLOR="Red"]New[/COLOR][/U][/B] List(Of String)

Public ReadOnly Property DepartmentList() As List(Of String)
    Get
        Return Me._departmentList
    End Get
End Property
VB.NET:
Private _departmentList As List(Of String)

Public ReadOnly Property DepartmentList() As List(Of String)
    Get
        If Me._departmentList Is Nothing Then
            Me._departmentList = [B][U][COLOR="Red"]New[/COLOR][/U][/B] List(Of String)
        End If

        Return Me._departmentList
    End Get
End Property
With or without lazy-loading, I am always creating the collection object before the property value is returned for the first time, so there's always an object returned by the property so you can call AddRange on that object. This is the proper way to expose collection via properties: create the collection internally and then expose it via a ReadOnly property. Callers can then get the collection object from the property and then add and remove items as much as they like, but the can never assign a whole new collection, or Nothing, to the property. That way, anyone who has a reference to that collection knows that they will always have a reference to the property value and not some collection that was replaced somewhere else in code.
 
Back
Top