Классы и массивы как инициализировать?

#vb.net #class #partial-classes

#vb.net #класс #частичные классы

Вопрос:

Я работаю над некоторыми частичными классами, но не могу понять, как это сделать. Это мои классы:

 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
 

И для класса FormGroup организация такая же.

Я хочу создавать частичные классы для расширения этих классов, поэтому, когда я использую все эти классы в другом проекте, мне приходится иметь дело только с (см.) самым верхним классом (Form), а не с другими классами (например, Info и FormGroup . Это то, что мне нравится делать:

 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
 

Но я не могу написать

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

потому что это массивы с классами. Как я могу это сделать в моем классе Form и Info?

Заранее спасибо.

Ответ №1:

Вы должны сначала создать массив, затем выполнить цикл по массиву и назначить каждый элемент. Кроме того, если у вас нет веской, веской причины, делайте это в конструкторе, а не в отдельном методе инициализации.

 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
 

В качестве альтернативы, если у вас много полей массива, и все они имеют конструкторы по умолчанию, вы могли бы создать FixedCollection класс, который инкапсулировал бы повторяющийся код инициализации.

 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
 

РЕДАКТИРОВАТЬ: Добавлены перегрузки конструктора, когда конструктора элемента недостаточно.

Если вы используете только конструкторы с параметром creator, вы можете удалить New ограничение на T .

Используйте перегрузки следующим образом:

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

End Class
 

Основываясь на ваших комментариях, кажется Init , что методы являются досадной необходимостью. Если возможно, я бы рекомендовал вам найти способ изменить сгенерированный конструктор, чтобы вызвать этот метод (определенный в сгенерированном коде с использованием частичных методов) для вас, а не заставлять вас вызывать его самостоятельно.

Комментарии:

1. Спасибо! Но как я могу сделать это в конструкторе, когда я использую частичный класс? Я не думаю, что у меня может быть конструктор в моем частичном классе, когда он существует в моем «оригинальном» классе? Или это неправильно?

2. @Liss Нет, вы не можете определить один и тот же метод в двух разных местах. Если другая часть частичного класса создает конструктор по умолчанию, вам придется использовать этот метод инициализации. Ни один из частичных классов, с которыми я сталкивался, не мешает мне создавать конструктор по умолчанию. Вам следует избегать использования частичных классов, если только одна из этих частей не сгенерирована инструментом (например, WinForm / WPF designers), поскольку они разделяют код без особой пользы. Использование FixedCollection , позволяет инициализировать встроенный (например: Private InfoField As New FixedCollection(Of Info) ) и полностью избежать проблемы с конструктором.

3. Спасибо! Да, мои «оригинальные» частичные классы генерируются автоматически и имеют конструктор, и я не могу изменить эти автоматически сгенерированные классы. Является ли для меня лучшим вариантом использовать частичные классы для расширения «оригинальных» классов?

4. @Liss В этом случае я бы предпочел использовать FixedCollection вместо массива, поскольку он может содержать логику инициализации. Если вызова конструктора для элементов коллекции недостаточно, вы можете изменить конструктор коллекции, чтобы использовать функцию создания элемента (см. Отредактированный ответ).

5. Спасибо, я действительно ценю ваше время!

Ответ №2:

Вы можете инициализировать массив класса следующим образом:

 Public FieldTypes As FieldTypeInfo() =  
    {  
    New FieldTypeInfo("Byte", 1),  
    New FieldTypeInfo("Int16", 2),  
    New FieldTypeInfo("Int32", 3),  
    New FieldTypeInfo("Integer", 3),  
    New FieldTypeInfo("Int64", 4),  
    New FieldTypeInfo("UInt16", 5),  
    New FieldTypeInfo("UInt32", 6),  
    New FieldTypeInfo("UInteger", 6),  
    New FieldTypeInfo("UInt64", 7)  
}