Как я могу получить доступ к его явно предоставленному конструктору в общей структуре VB.NET? - PullRequest
3 голосов
/ 08 апреля 2019

Прежде всего, чего я хочу достичь:

Я хочу расширить тип данных значения, предоставив дополнительные свойства, особенно для проверки диапазонов, предоставляемых во время объявления.Я хочу, чтобы новый тип данных также был типом значения.

Сравните с Ada:

subtype Day_Number is Integer range 1 .. 31;

Идеально, но, очевидно, не реализуемо, будет:

Dim DayNumber As Int64 Range 1 To 31

Тем не менее, я был бы рад:

Dim DayNumber As RangeInt64(1, 31)

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

Моя попытка:

Поскольку я не могу наследовать от структур, чтобы расширить их, я попытался включить структуру в структуру как член.

В модуле у меня есть эта структура:

Friend Structure SRangeValueType(Of T)
    Private lMinimum As T
    Private lMaximum As T

    Friend Property Minimum As T
        Get
            Return lMinimum
        End Get
        Set(tValue As T)
            lMinimum = tValue
        End Set
    End Property

    Friend Property Maximum As T
        Get
            Return lMaximum
        End Get
        Set(tValue As T)
            lMaximum = tValue
        End Set
    End Property

    Friend Sub New(Minimum As T, Maximum As T)
        lMinimum = Minimum
        lMaximum = Maximum
    End Sub
End Structure

Я пытаюсь использовать эту универсальную структуру в качестве члена другой структуры (конкретного типа Int64):

Public Structure RangeInt64
    Private Range As SRangeValueType(Of Int64)
End Structure

Однако этот конструктор не использует два аргумента.

Скажем, я хочу инициализировать Range (единственный член структуры RangeInt64) значениями 100 и 200 для минимума и максимума, соответственно

Мне не разрешено использовать что-то вроде:

    Private Range As SRangeValueType(Of Int64)(100,200)

Каков правильный синтаксис для предоставления моих значений универсальному конструктору?

1 Ответ

0 голосов
/ 08 апреля 2019

Обычно, если вы добавляете конструктор в структуру, вы можете вызвать его с помощью ключевого слова New:

Dim x As SRangeValueType(Of Int64)  ' Calls the default, infered, parameter-less constructor
Dim y As New SRangeValueType(Of Int64)(100, 200)  ' Calls the explicitly defined constructor

Однако проблема не в этом. Проблема заключается в том, что вы пытаетесь установить значение по умолчанию для не общего поля в структуре. Это то, что никогда не допускается. Все не общие поля в структурах должны по умолчанию иметь свои значения по умолчанию (т.е. Nothing). Например:

Public Structure RangeInt64
    Private x As Integer = 5  ' Error: Initializers on structure members are valid only for 'Shared' members and constants
    Private y As New StringBuilder()  ' Error: Non-shared members in a structure cannot be declared 'New'
End Structure

И, как вы, возможно, уже знаете, вы не можете переопределить конструктор по умолчанию, выводимый без параметров, также в структуре:

Public Structure RangeInt64
    Public Sub New()  ' Error: Structures cannot declare a non-shared 'Sub New' with no parameters
        x = 5
        y = New StringBuilder()
    End Sub

    Private x As Integer
    Private y As StringBuilder
End Structure

Таким образом, вы застряли. По замыслу, когда используется конструктор по умолчанию, все поля в структуре всегда должны по умолчанию Nothing. Однако, если вам действительно нужно, чтобы это была структура, и вы не можете просто преобразовать ее в класс, и вам действительно нужно изменить значение по умолчанию, вы можете теоретически подделать его для работы, используя свойство для переноса поле:

Public Structure RangeInt64
    Private _Range As SRangeValueType(Of Int64)
    Private _RangeInitialized As Boolean
    Private Property Range As SRangeValueType(Of Int64)
        Get
            If Not _RangeInitialized Then
                _Range = New SRangeValueType(Of Int64)(100, 200)
                _RangeInitialized = True
            End If
            Return _Range
        End Get
        Set(value As SRangeValueType(Of Int64))
            _Range = value
        End Set
    End Property
End Structure

Однако само собой разумеется, что это довольно грубое и его следует избегать, если это возможно.

Обновление

Теперь, когда вы предоставили более подробную информацию о том, что вы пытаетесь выполнить, я думаю, что у меня может быть лучшее решение для вас. Вы правы, что структуры не поддерживают наследование, но они поддерживают интерфейсы. Таким образом, если все, что вам нужно, это набор типов диапазонов, по одному на тип значения, все с одинаковыми минимальными и максимальными свойствами, но все возвращающие разные предопределенные значения, то вы можете сделать что-то вроде этого:

Private Interface IRangeValueType(Of T)
    ReadOnly Property Minimum As T
    ReadOnly Property Maximum As T
End Interface

Private Structure RangeInt64
    Implements IRangeValueType(Of Int64)

    Public ReadOnly Property Minimum As Long Implements IRangeValueType(Of Int64).Minimum
        Get
            Return 100
        End Get
    End Property

    Public ReadOnly Property Maximum As Long Implements IRangeValueType(Of Int64).Maximum
        Get
            Return 200
        End Get
    End Property
End Structure
...