Есть ли лучший способ привести UDT к другому типу? - PullRequest
0 голосов
/ 16 мая 2019

У меня есть класс, который содержит свойство "value", которое содержит любой тип данных, и поэтому является объектом. Во включенном примере «значением» является тип «nonNegativeInteger». Мне нужно уметь удваивать структуру, и я нашел единственный способ сделать это - неловко:

CDbl(CTypeDynamic(obj, GetType(Double)))

вот код в простом проекте vb windows forms:

Option Strict On
Option Explicit On
Imports System.Dynamic
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim av = New anyValue
        av.value = 4
        Dim obj As Object = av          'box av     
        Dim dAv = CDbl(av)              'works
        'Dim dObj = CDbl(obj)            'fails (invalid cast)
        'Dim fAv = getDouble(av)         'fails
        'Dim fObj = getDouble(obj)       'fails
        Dim kAv = getDoubleKludge(av)   'works  
        Dim fObj = getDoubleKludge(obj) 'works
        Stop
    End Sub
    Private Function getDouble(obj As Object) As Double
        Return CDbl(obj)
    End Function
    Private Function getDoubleKludge(obj As Object) As Double
        Return CDbl(CTypeDynamic(obj, GetType(Double)))
    End Function
End Class
Public Class anyValue
    Private _value As Object
    Public Property value As Object
        Get
            Return _value
        End Get
        Set(obj As Object)
            _value = obj
        End Set
    End Property
    Public Shared Widening Operator CType(obj As anyValue) As Double
        Return CDbl(obj.value)
    End Operator
End Class
Public Structure nonNegativeInteger
    Private _value As Integer
    Public Property value As Integer
        Get
            Return _value
        End Get
        Set(val As Integer)
            If val >= 0 Then
                _value = val
            Else
                _value = 0
                Throw New ArgumentOutOfRangeException
            End If
        End Set
    End Property
    Public Sub New(i As Integer)
        If i >= 0 Then
            _value = i
        Else
            _value = 0
            Throw New ArgumentOutOfRangeException
        End If
    End Sub
    Public Sub New(s As String)
        If Not Integer.TryParse(s, _value) OrElse _value < 0 Then
            _value = 0
            Throw New ArgumentOutOfRangeException
        End If
    End Sub
    Public Shared Widening Operator CType(ByVal o As nonNegativeInteger) As String
        Return o.ToString
    End Operator
    Public Shared Narrowing Operator CType(ByVal s As String) As nonNegativeInteger
        Return New nonNegativeInteger(s)
    End Operator
    Public Shared Widening Operator CType(ByVal o As nonNegativeInteger) As Double
        Return CDbl(o.value)
    End Operator
    Public Shared Narrowing Operator CType(ByVal d As Double) As nonNegativeInteger
        If d > Integer.MaxValue OrElse d < 0 Then
            Throw New ArgumentOutOfRangeException
            Return Nothing
        Else
            Return New nonNegativeInteger(CInt(d))
        End If
    End Operator
    Public Overrides Function ToString() As String
        Return _value.ToString()
    End Function
    Public Function toDouble() As Double
        Return CDbl(_value)
    End Function
End Structure
...