Vb.net 如何在Visual Basic.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值分配给我的
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下睫毛。:)这两个答案都很清楚,质量也很好。很难在这两个答案之间做出选择,但我最终还是选择了你的答案。感谢你们两人的帮助!哈哈,我们几乎同时得出了我们的答案,概念非常相似。很高兴看到这样