Question Accessing a class within a class

MrNoob

New member
Joined
Feb 23, 2011
Messages
3
Programming Experience
1-3
I have two classes, A and B, with B as a property of A:
VB.NET:
Public Class A
    Private aField As String
    Private itemField() As B
    Public Property note() As String
      Get
        Return Me.aField
      End Get
      Set(ByVal value As String)
        Me.aField = value
      End Set
    End Property

    Public Property item() As B()
      Get
        Return Me.itemField
      End Get
      Set(ByVal value As B())
        Me.itemField = value
      End Set
    End Property

End Class

Public Class B
    Private bField As String
    Public Property name() As String
      Get
        Return Me.bField
      End Get
      Set(ByVal value As String)
        Me.bField = value
      End Set
    End Property
End Class
' if I call the A class everything is OK:
Dim x As New A
x.note = "Hello"
'but if I try to instantiate B I get errors:
x.item(0) = New B '-Throws a runtime error 'Object reference not set to instance' error, or
x.item = New B 'throws a compile time error 'Value of type 'B' cannot be converted to '1-dimensional array of B'



I know this must be a very simple thing but I am stuck. How can I instantiate x.item()? Thanks
 
x.item(0) = New B '-Throws a runtime error 'Object reference not set to instance' error, or
x.item = New B 'throws a compile time error 'Value of type 'B' cannot be converted to '1-dimensional array of B'
So is the intention that the property contain a single item or an array of items? You have declared it as the latter, which uninitialized is an empty array. Though naming the property 'Item' would suggest that its purpose is for a single item.
 
Here's an example of the "proper" way to do it:
VB.NET:
Public Class Person

    Private _givenName As String
    Private _familyName As String


    Public Property GivenName() As String
        Get
            Return _givenName
        End Get
        Set(ByVal value As String)
            _givenName = value
        End Set
    End Property

    Public Property FamilyName() As String
        Get
            Return _familyName
        End Get
        Set(ByVal value As String)
            _familyName = value
        End Set
    End Property

End Class


Public Class PersonCollection
    Inherits System.Collections.ObjectModel.Collection(Of Person)
End Class


Public Class Group

    Private _leader As Person
    Private _members As New PersonCollection


    Public Property Leader() As Person
        Get
            Return _leader
        End Get
        Set(ByVal value As Person)
            _leader = value
        End Set
    End Property

    Public ReadOnly Property Members() As PersonCollection
        Get
            Return _members
        End Get
    End Property

End Class
The Person class represents a single object and the PersonCollection represents multiple objects, containing zero or more Person objects. You would use the Group class like this:
VB.NET:
Dim grp As New Group

grp.Leader = New Person

Dim prsn As Person = grp.Leader

grp.Members.Add(New Person)

prsn = grp.Members(0)
This pattern of exposing a collection via a read-only property is repeated over and over again throughout the .NET Framework.

Note also that, if it's not going to be exposed beyond the assembly it's declared in, it's considered OK to omit the custom collection and just use a standard List:
VB.NET:
Public Class Person

    Private _givenName As String
    Private _familyName As String


    Public Property GivenName() As String
        Get
            Return _givenName
        End Get
        Set(ByVal value As String)
            _givenName = value
        End Set
    End Property

    Public Property FamilyName() As String
        Get
            Return _familyName
        End Get
        Set(ByVal value As String)
            _familyName = value
        End Set
    End Property

End Class


Public Class Group

    Private _leader As Person
    Private _members As New List(Of Person)


    Public Property Leader() As Person
        Get
            Return _leader
        End Get
        Set(ByVal value As Person)
            _leader = value
        End Set
    End Property

    Public ReadOnly Property Members() As List(Of Person)
        Get
            Return _members
        End Get
    End Property

End Class
Code to use it doesn't change.
 
Back
Top