Vb.net 如何在Visual Basic.NET中实现自定义数字数据类型?

Vb.net 如何在Visual Basic.NET中实现自定义数字数据类型?,vb.net,types,numbers,Vb.net,Types,Numbers,Visual Basic.NET提供了几种内置的数值类型(Integer、Double等),每种类型都有自己的有效值范围。在大多数情况下,这些都适合我正在做的事情 然而,有时我发现自己需要一个具有自己的自定义有效值范围的数值类型。假设我经常使用表示一个数量的值,该数量只能在两个值之间(例如,-20到500,作为一个假设示例),并且始终是一个整数。这些要求由使用的类型强制执行。让我们将此类型称为SpecialInteger 我希望能够使用我的自定义类型执行以下操作: 将Integer值分配给我的

Visual Basic.NET提供了几种内置的数值类型(
Integer
Double
等),每种类型都有自己的有效值范围。在大多数情况下,这些都适合我正在做的事情

然而,有时我发现自己需要一个具有自己的自定义有效值范围的数值类型。假设我经常使用表示一个数量的值,该数量只能在两个值之间(例如,-20到500,作为一个假设示例),并且始终是一个整数。这些要求由使用的类型强制执行。让我们将此类型称为
SpecialInteger

我希望能够使用我的自定义类型执行以下操作:

  • Integer
    值分配给我的类型:

    Dim someSpecialValue As SpecialInteger = 30
    
  • 如果您试图为其指定一个超出我上面提到的范围的值,请抛出:

  • 如果您尝试指定的值在范围内,但不是整数,则抛出类似于的值:

    Dim alsoNotAllowedValue As SpecialInteger = 1.5 ' Also invalid.
    
  • SpecialInteger
    识别为
    Integer
    的特例,以便我可以继续在赋值和算术表达式中使用它,如:

    Dim someInt As Integer
    Dim myOtherValue As SpecialInteger = 234
    
    ' Neither of these statements should produce an error:
    someInt = myOtherValue
    someInt = myOtherValue + 5
    
……等等。你明白了


然而,我在网上找不到任何关于我应该如何做这件事的信息。我猜这将被实现为某种
结构
,带有一个获取或设置值的属性,但我不知道还需要什么来完全正确地实现我的类型。是否需要遵循约定或接口?任何建议、资源或操作方法都将不胜感激。

一个自己的
结构将是可行的

我最近实现了类似的功能,因此我可以给您一些有用的提示:

Public Structure SpecialInteger
    'private field to hold the integer value.
    Private _value As Integer

    'internal property with range check in the setter
    Friend Property Value() As Integer
        Get
            Return _value
        End Get
        Set
            If value > 500 Then
                Throw New OverflowException("Value must be <= 500")
            End If
            _value = value 'value from setter
        End Set
    End Property

    'If you want to compare two SpecialIntegers
    Public Overrides Function Equals(obj As Object) As Boolean
        If Not (TypeOf obj Is SpecialInteger) Then
            Return False
        End If
        Dim s = CType(obj, SpecialInteger)
        Return s.Value = Me.Value
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return Value.GetHashCode()
    End Function

    Public Overrides Function ToString() As String
       Return Value.ToString()
    End Function

    'If you want to comapre with =, <> >, < or do math ops +, -, 
    Public Shared Operator =(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
        Return s1.Equals(s2)
    End Operator

    'same for <>
    Public Shared Operator <>(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
     '...
    End Operator

    Public Shared Operator <(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
        Return s1.Value < s2.Value
    End Operator

    'same for >
    Public Shared Operator >(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
           '...
    End Operator

    Public Shared Operator +(s1 As SpecialInteger, s2 As SpecialInteger) As Integer
        Return s1.Value + s2.Value
    End Operator

    'same for -
    Public Shared Operator -(s1 As SpecialInteger, s2 As SpecialInteger) As Integer
      '...
    End Operator

    'Dim si as SpecialInteger = 5
    Public Shared Widening Operator CType(s As SpecialInteger) As Integer
        Return s.Value
    End Operator

    'Dim i as Integer = si
    Public Shared Widening Operator CType(s As Integer) As SpecialInteger
        Return New SpecialInteger() With  {Key .Value = s }
    End Operator
End Structure

附言:我用C语言写了这篇文章,并使用了一个到VB的在线代码转换器。希望一切都是正确的。

一个自己的
结构将是可行的

我最近实现了类似的功能,因此我可以给您一些有用的提示:

Public Structure SpecialInteger
    'private field to hold the integer value.
    Private _value As Integer

    'internal property with range check in the setter
    Friend Property Value() As Integer
        Get
            Return _value
        End Get
        Set
            If value > 500 Then
                Throw New OverflowException("Value must be <= 500")
            End If
            _value = value 'value from setter
        End Set
    End Property

    'If you want to compare two SpecialIntegers
    Public Overrides Function Equals(obj As Object) As Boolean
        If Not (TypeOf obj Is SpecialInteger) Then
            Return False
        End If
        Dim s = CType(obj, SpecialInteger)
        Return s.Value = Me.Value
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return Value.GetHashCode()
    End Function

    Public Overrides Function ToString() As String
       Return Value.ToString()
    End Function

    'If you want to comapre with =, <> >, < or do math ops +, -, 
    Public Shared Operator =(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
        Return s1.Equals(s2)
    End Operator

    'same for <>
    Public Shared Operator <>(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
     '...
    End Operator

    Public Shared Operator <(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
        Return s1.Value < s2.Value
    End Operator

    'same for >
    Public Shared Operator >(s1 As SpecialInteger, s2 As SpecialInteger) As Boolean
           '...
    End Operator

    Public Shared Operator +(s1 As SpecialInteger, s2 As SpecialInteger) As Integer
        Return s1.Value + s2.Value
    End Operator

    'same for -
    Public Shared Operator -(s1 As SpecialInteger, s2 As SpecialInteger) As Integer
      '...
    End Operator

    'Dim si as SpecialInteger = 5
    Public Shared Widening Operator CType(s As SpecialInteger) As Integer
        Return s.Value
    End Operator

    'Dim i as Integer = si
    Public Shared Widening Operator CType(s As Integer) As SpecialInteger
        Return New SpecialInteger() With  {Key .Value = s }
    End Operator
End Structure

附言:我用C语言写了这篇文章,并使用了一个到VB的在线代码转换器。希望一切都是正确的。

您可以通过定义您的
SpecialInteger
类型来实现您的目标

对于
SpecialInteger
Integer
之间的隐式类型转换,需要
加宽
运算符。此外,还需要一个
+
操作符

像这样的事情会让你开始

Public Structure SpecialInteger
    Const min As Int32 = -25
    Const max As Int32 = 500
    Private backing As Int32

    Public Sub New(value As Int32)
        Me.Value = value
    End Sub

    Public Property Value As Int32
        Get
            Return Me.backing
        End Get
        Set(value As Int32)
            If Validates(value) Then
                Me.backing = value
            Else
                Throw New ArgumentOutOfRangeException(String.Format("min: {0}, max: {1}, Value: {2}", min, max, value))
            End If
        End Set
    End Property

    Private Function Validates(value As Int32) As Boolean
        Return (min <= value) AndAlso (value <= max)
    End Function

    Public Shared Widening Operator CType(ByVal value As SpecialInteger) As Int32
        Return value.backing
    End Operator

    Public Shared Widening Operator CType(ByVal value As Int32) As SpecialInteger
        Return New SpecialInteger(value)
    End Operator

    Public Shared Operator +(v1 As Int32, v2 As SpecialInteger) As SpecialInteger
        Return New SpecialInteger(v1 + v2.backing)
    End Operator
End Structure
公共结构专用工具
常量最小值为Int32=-25
常量最大值为Int32=500
作为Int32的私人支持
公共子新建(值为Int32)
价值=价值
端接头
公共财产价值为Int32
得到
给我回电话
结束
设置(值为Int32)
如果验证(值),则
Me.backing=价值
其他的
抛出新的ArgumentOutForRangeException(String.Format(“min:{0},max:{1},值:{2}”,min,max,Value))
如果结束
端集
端属性
私有函数验证(值为Int32)为布尔值

Return(min您可以通过在
SpecialInteger
类型上定义各种属性来实现您的目标

对于
SpecialInteger
Integer
之间的隐式类型转换,需要
加宽
运算符。此外,还需要
+
运算符

像这样的事情会让你开始

Public Structure SpecialInteger
    Const min As Int32 = -25
    Const max As Int32 = 500
    Private backing As Int32

    Public Sub New(value As Int32)
        Me.Value = value
    End Sub

    Public Property Value As Int32
        Get
            Return Me.backing
        End Get
        Set(value As Int32)
            If Validates(value) Then
                Me.backing = value
            Else
                Throw New ArgumentOutOfRangeException(String.Format("min: {0}, max: {1}, Value: {2}", min, max, value))
            End If
        End Set
    End Property

    Private Function Validates(value As Int32) As Boolean
        Return (min <= value) AndAlso (value <= max)
    End Function

    Public Shared Widening Operator CType(ByVal value As SpecialInteger) As Int32
        Return value.backing
    End Operator

    Public Shared Widening Operator CType(ByVal value As Int32) As SpecialInteger
        Return New SpecialInteger(value)
    End Operator

    Public Shared Operator +(v1 As Int32, v2 As SpecialInteger) As SpecialInteger
        Return New SpecialInteger(v1 + v2.backing)
    End Operator
End Structure
公共结构专用工具
常量最小值为Int32=-25
常量最大值为Int32=500
作为Int32的私人支持
公共子新建(值为Int32)
价值=价值
端接头
公共财产价值为Int32
得到
给我回电话
结束
设置(值为Int32)
如果验证(值),则
Me.backing=价值
其他的
抛出新ArgumentOutOfRangeException(String.Format(“min:{0},max:{1},Value:{2}”,min,max,Value))
如果结束
端集
端属性
私有函数验证(值为Int32)为布尔值

返回(最小范围验证不需要自定义数据类型。您所描述的只是将验证/范围括号移到某个位置class@Plutonix但是,每次我想知道我的
Integer
变量是否是有效值时,我不需要记住调用该类来验证它们吗?我倾向于认为这样会更干净d如果我定义了自己的类型来在后台自动执行此检查,则不太容易出错。顺便说一句……这是一个结构良好且整体良好的问题范围验证,不需要自定义数据类型。您所描述的只是将验证/范围括号移到某个位置class@Plutonix那我就不用记着叫它了吧类来验证我的
Integer
变量,每次我想看看它们是否是有效值?我倾向于认为,如果我在后台定义了自己的类型来自动执行此检查,会更干净、更不容易出错。顺便说一句……这是一个结构良好、整体良好的问题,不应该是Int32到SpecialLinteger箭头转换?@Craig,严格地说,是的,它应该是一个缩小转换。但是OP要求允许Int32隐式转换为SpecialLinteger,这需要一个加宽操作符来完成。因此,为了在IDE中方便起见,我打破了规则,在不应该的地方可能会发生运行时错误(加宽操作在运行时应始终成功)。我用湿面条打10下睫毛。:)这两个答案都很清楚,质量也很好。很难在这两个答案之间做出选择,但我最终还是选择了你的答案。感谢你们两人的帮助!哈哈,我们几乎同时得出了我们的答案,概念非常相似。很高兴看到这样