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

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

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 организация такая же.

Я хочу создать частичные классы для расширения этих классов, поэтому, когда я использую все эти классы в другом проекте, мне приходится иметь дело только (см.) с самым верхним классом (формой), а не с другими классами (такими как 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?

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


person Liss    schedule 01.11.2011    source источник


Ответы (2)


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

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

EDIT: добавлены перегрузки конструктора, когда конструктора элемента недостаточно.

Если вы используете только конструкторы с параметром создателя, вы можете удалить ограничение 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 являются досадной необходимостью. Если возможно, я бы порекомендовал вам найти способ изменить сгенерированный конструктор для вызова этого метода (определенного в сгенерированном коде с использованием частичных методов) для вас, а не заставлять вас вызывать его самостоятельно.

person Gideon Engelberth    schedule 01.11.2011
comment
Спасибо! Но как я могу сделать это в конструкторе, когда я использую разделяемый класс? Я не думаю, что у меня может быть конструктор в моем частичном классе, когда он существует в моем исходном классе? Или это неправильно? - person Liss; 01.11.2011
comment
@Liss Нет, вы не можете определить один и тот же метод в двух разных местах. Если другая часть частичного класса создает конструктор по умолчанию, вы застряли с помещением этого метода Init. Ни один из частичных классов, с которыми я столкнулся, не мешает мне создать конструктор по умолчанию. Вам следует избегать использования частичных классов, если только одна из этих частей не создается инструментом (например, конструкторами WinForm/WPF), поскольку они разделяют код без особой пользы. Использование FixedCollection позволяет выполнить встроенную инициализацию (например: Private InfoField As New FixedCollection(Of Info)) и полностью избежать проблем с конструктором. - person Gideon Engelberth; 01.11.2011
comment
Спасибо! Да, мои исходные частичные классы генерируются автоматически и имеют конструктор, и я не могу изменить эти автоматически созданные классы. Является ли тогда лучшим вариантом для меня использовать частичные классы для расширения исходных классов? - person Liss; 01.11.2011
comment
@Liss В этом случае я бы склонялся к использованию FixedCollection вместо массива, поскольку он может содержать логику инициализации. Если вызова конструктора для элементов коллекции недостаточно, вы можете изменить конструктор коллекции, чтобы использовать функцию создания элемента (см. отредактированный ответ). - person Gideon Engelberth; 02.11.2011
comment
Спасибо, я очень ценю ваше время! - person Liss; 02.11.2011

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

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)  
}  
person JBStCyr    schedule 10.04.2020