vb.net - 在通用 VB.NET 结构中,如何访问其显式提供的构造函数?

标签 vb.net data-structures struct constructor

首先,我想达到的目的:

我想通过提供额外的属性来扩展值数据类型,尤其是为了验证在声明时提供的范围。我希望新数据类型也成为值类型。

与 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)

将我的值提供给通用构造函数的正确语法是什么?

最佳答案

通常情况下,如果你给一个结构添加一个构造函数,你可以使用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

不言而喻,它非常恶心,应尽可能避免。

更新

既然您已经提供了有关您要完成的目标的更多详细信息,我想我可能会为您提供更好的解决方案。你说得对,结构不支持继承,但它们支持的是接口(interface)。因此,如果您只需要一堆范围类型,每个值类型一个,都具有相同的最小值和最大值属性,但都返回不同的预定值,那么您可以这样做:

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

关于vb.net - 在通用 VB.NET 结构中,如何访问其显式提供的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55574690/

相关文章:

mysql - 无法调试 Windows 窗体程序

c - 删除单向链表中所有出现的元素

swift - Plist 与结构不同的字典

c - 编码解码请发现故障

c++ - C++ 中的 LRU 缓存

c - 如何在 C 中用随机数据初始化结构?

vb.net - 暴露 WCF 服务无法通过 windows 防火墙检索对象

vb.net - Ftp 上传大文件导致 VB.Net 应用程序卡在 Stream.Close() 上

sql-server - 调用 API 的 SQL Server 程序集

algorithm - 什么是对这些特征进行分组的良好数据结构?什么算法可以用于插入和检索?