Search code examples
vb.netclasspartial-classes

Classes and arrays how to initialize?


I’m working on some partial classes but I can’t figure out how to do it. This is my classes:

Partial Public Class Form
    Private InfoField() As Info

    Private FormgroupField() As FormGroup

    Private tittle As String


    Public Property Info() As Info()
    Get
        Return Me. InfoField
    End Get
    Set
        Me. InfoField = value
    End Set
    End Property

Public Property FormGroup() As FormGroup()
    Get
        Return Me.GromGroupField
    End Get
    Set
        Me.FormGroupField = value
    End Set
    End Property

   Public Property tittle() As String
    Get
        Return Me.tittleField
    End Get
    Set
        Me.tittleField = value
    End Set
 End Property
End class



Partial Public Class Info
      Private ChangeFormField() As ChangeForm

    Private formYearField() As FormYea

    Private idField As String

    Public Property ChangeForm() As ChangeForm()
    Get
        Return Me.changeFormField
    End Get
    Set
        Me.changeFormField = value
    End Set
    End Property

   Public Property FormYear() As FormYear()
    Get
        Return Me.formYearField
    End Get
    Set
        Me.formYearField = value
    End Set
    End Property

   Public Property id() As String
    Get
        Return Me.idField
    End Get
    Set
        Me.idField = value
    End Set
    End Property    

  End Class

 Partial Public Class ChangeForm
Private idField As String

    Private valueField As String

<properties goes here>
End Class

Partial Public Class FormYear

    Private idField As String

    Private valueField As String

<properties goes here>
 End Class

And for the class FormGroup the organization is the same.

I want to build partial classes to extend these classes, so when I use all this classes in another project I only have to deal with (see) the topmost class (Form) and not the other classes (like Info and FormGroup. This is what I like to do:

Partial Public Class Form
 Public Sub Init()
    Me.Info = New Info
    Me.FormGroup = New FormGroup

    Me.Info.Init()
    Me.FormGroup.Init()
End Sub

End Class

Partial Public Class Info
 Public Sub Init()
    Me.FormYear = New FormYear
    Me.ChangeForm = New ChangeForm

    Me.changeForm.Init()
End Sub

But I can’t write

Me.Info = New Info
Me.FormGroup = New FormGroup

because it is arrays with classes. How can I do it in my Form and Info class?

Thanks in advance.


Solution

  • You must first create an array, then loop over the array and assign each element. Also, unless you have a good, strong reason, do this in the constructor rather than a separate init method.

    Public Class Form
        Public Sub New()
            'In VB, you give the max index, not the length.
            'I prefer listing this as (whatever I want for length) - 1
            Me.Info = New Info(size - 1) {}
            For i = 0 to size - 1
                Me.Info(i) = New Info()
            Next
            'similarly for other fields
        End Sub
    End Class
    

    Alternatively, if you find yourself with a lot of array fields, and they all have default constructors, you could create a FixedCollection class that would encapsulate the repetitive initialization code.

    Public Class FixedCollection(Of T As New)
        Inherits Collection(Of T)
    
        Public Sub New(ByVal size As Integer)
            MyBase.New(New T(size - 1) {})
            For i = 0 to size - 1
                Me.Items(i) = New T()
            Next
        End Sub
    
        'alternate constructors if you need additional initialization
        'beyond construction of each element
        Public Sub New(ByVal size As Integer, ByVal creator As Func(Of T))
            MyBase.New(New T(size - 1) {})
            If creator Is Nothing Then Throw New ArgumentNullException("creator")
            For i = 0 to size - 1
                Me.Items(i) = creator()
            Next
        End Sub
        'this overload allows you to include the index in the collection
        'if it would matter to creation
        Public Sub New(ByVal size As Integer, ByVal creator As Func(Of Integer, T))
            MyBase.New(New T(size - 1) {})
            If creator Is Nothing Then Throw New ArgumentNullException("creator")
            For i = 0 to size - 1
                Me.Items(i) = creator(i)
            Next
        End Sub
    
        'other collection overrides as needed here
    
    End Class
    

    EDIT: Added constructor overloads for when an element constructor is not enough.

    If you only use the constructors with a creator parameter, you could remove the New constraint on T.

    Use the overloads as follows:

    Public Class Form
        Private InfoField As New FixedCollection(Of Info)(10,  
                    Function()
                        Dim ret As New Info()
                        ret.Init()
                    End Function)
    
    End Class
    

    Based on your comments, it seems like the Init methods are an unfortunate necessity. If possible, I would recommend that you find a way to get the generated constructor changed to call this method (defined in the generated code using partial methods) for you rather than forcing you to call it yourself.