#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)
}