Vb.net 如何重新编写包含检查等式运算符重载中三个可为null(Of T)值的条件逻辑?

Vb.net 如何重新编写包含检查等式运算符重载中三个可为null(Of T)值的条件逻辑?,vb.net,Vb.net,因此,我正在为一个自定义对象编写等式操作符重载(操作符=()),由此产生的If条件的混乱只是一个麻烦。但到目前为止,它似乎是检查值以匹配此对象的特定行为的唯一明智的方法 这些规则是: Num1是必需的、句点和左右两个操作数,并且必须等于True。否则就错了 Num2是可选的,但如果指定,则左操作数和右操作数都必须存在,并且必须等于True。否则就错了 Num3是可选的,但仅当Num2也存在时才能指定。否则就错了 Num3(如果指定)对于左操作数和右操作数都必须存在,并且对于True必须相等。否则

因此,我正在为一个自定义对象编写等式操作符重载(
操作符=()
),由此产生的If条件的混乱只是一个麻烦。但到目前为止,它似乎是检查值以匹配此对象的特定行为的唯一明智的方法

这些规则是:

  • Num1是必需的、句点和左右两个操作数,并且必须等于True。否则就错了
  • Num2是可选的,但如果指定,则左操作数和右操作数都必须存在,并且必须等于True。否则就错了
  • Num3是可选的,但仅当Num2也存在时才能指定。否则就错了
  • Num3(如果指定)对于左操作数和右操作数都必须存在,并且对于True必须相等。否则就错了


  • 到目前为止,我已经做到了:

    Public Shared Operator =(ByVal lhOp As MyObj, ByVal rhOp As MyObj) As Boolean
        If lhOp Is Nothing Then _
            Return rhOp Is Nothing
    
        If rhOp Is Nothing Then _
            Return lhOp Is Nothing
    
        Dim tmpBool As Boolean = ((lhOp.Num1.HasValue AndAlso rhOp.Num1.HasValue) AndAlso (lhOp.Num1.Value = rhOp.Num1.Value))
    
        '// If tmpbool is 'True', then see if the Num2 HasValue params are equal.
        If tmpBool Then
            If (lhOp.Num2.HasValue = rhOp.Num2.HasValue) Then
                '// They match.  Now, do they have any data?
                If (lhOp.Num2.HasValue AndAlso rhOp.Num2.HasValue) Then
                    '// Num2 has a value.  See if the left and right operands
                    '// match each other.
                    If (lhOp.Num2.Value = rhOp.Num2.Value) Then
                        '// Num2 matches, so see if Num3 HasValue params
                        '// are equal.
                        If (lhOp.Num3.HasValue = rhOp.Num3.HasValue) Then
                            '// They match.  Now, do they have any data?
                            If (lhOp.Num3.HasValue AndAlso rhOp.Num3.HasValue) Then
                                '// Num3 has a value.  See if the left and right operands
                                '// match each other.
                                If (lhOp.Num3.Value = rhOp.Num3.Value) Then
                                    '// All three parameters match, return 'True'.
                                    Return True
                                Else
                                    '// Num3 failed to match, return 'False'.
                                    Return False
                                End If
                            Else
                                '// No data in Num3, return true.
                                Return True
                            End If
                        Else
                            '// Num3.HasValues do not match, return false.
                            Return False
                        End If
                    Else
                        '// Num2 failed to match, return 'False'.
                        Return False
                    End If
                Else
                    '// No Num2, so we cannot have a Num3 specified as well.
                    If (lhOp.Num3.HasValue OrElse rhOp.Num3.HasValue) Then _
                        Return False
    
                    '// Return true.
                    Return True
                End If
            Else
                '// Num2.HasValues do not match, return false.
                Return False
            End If
        End If
    
        '// Default is false.
        Return False
    End Operator
    


    我可以使用三元条件将其分解为下面的代码块,它看起来更优雅,但更模糊,不适合进行适当的维护:

        Return If(((lhOp.Num1.HasValue AndAlso rhOp.Num1.HasValue) AndAlso
                   (lhOp.Num1.Value = rhOp.Num1.Value)),
                  If((lhOp.Num2.HasValue = rhOp.Num2.HasValue),
                     If((lhOp.Num2.HasValue AndAlso rhOp.Num2.HasValue),
                        If((lhOp.Num2.Value = rhOp.Num2.Value),
                           If((lhOp.Num3.HasValue = rhOp.Num3.HasValue),
                              If((lhOp.Num3.HasValue AndAlso rhOp.Num3.HasValue),
                                 If((lhOp.Num3.Value = rhOp.Num3.Value),
                                    True, False),
                                True),
                            False),
                        False),
                    If((lhOp.Num3.HasValue OrElse rhOp.Num3.HasValue), False, True)),
                False),
            False)
    



    我还知道我可以将检查的元素缓存到布尔值中,然后使用它们来减少文本量。但这似乎只是为了代码可读性而浪费周期。所以我想知道So社区是否有更好的想法来重新组织它,以防我的检查过于冗长。

    我想你会发现这里大多数已经编程一段时间的人都会建议尽快从方法返回。否则,您将永远缩进代码,并尝试将逻辑与结尾XXX或大括号匹配

    因此,这个简化类应该与您的类大致匹配:

    Public Class MyObj
        Public Property Num1 As Boolean?
        Public Property Num2 As Boolean?
        Public Property Num3 As Boolean?
        Public Sub New(ByVal n1 As Boolean?, ByVal n2 As Boolean?, ByVal n3 As Boolean?)
            Me.Num1 = n1
            Me.Num2 = n2
            Me.Num3 = n3
        End Sub
    End Class
    
    根据您的逻辑,此方法应作为比较器工作:

    Public Shared Function CheckEquals(ByVal lhOp As MyObj, ByVal rhOp As MyObj) As Boolean
        '//Num1 is required, also check the others for mismatched properties
        If (Not lhOp.Num1.HasValue) OrElse (Not rhOp.Num1.HasValue) OrElse (lhOp.Num2.HasValue <> rhOp.Num2.HasValue) OrElse (lhOp.Num3.HasValue <> rhOp.Num3.HasValue) Then Return False
    
        '//Num1 is required and must have the same value
        If (lhOp.Num1.Value <> rhOp.Num1.Value) Then Return False
    
        '//If Num2 is present the values must match
        If (lhOp.Num2.HasValue) AndAlso (lhOp.Num2.Value <> rhOp.Num2.Value) Then Return False
        '//Num3 is optional but Num2 must be set
        If lhOp.Num3.HasValue AndAlso (Not lhOp.Num2.HasValue OrElse (lhOp.Num3.Value <> lhOp.Num3.Value)) Then Return False
    
        Return True
    End Function
    

    另外,我应该补充一点,您应该花点时间考虑一下空比较。我个人更喜欢在编写比较方法且其中一个对象为null时抛出异常。返回true/false肯定是正确的,我只是觉得以后调试起来比较困难。这是一个非常好的答案。今天晚些时候,我会对它进行测试,并进行检查。我也同意尽早从函数返回…这是我正在学习打破的一个习惯,通过查看Reflector,我在核心框架中注意到了很多东西。此外,当一方或另一方为false时返回是我从Reflector中获得的其他东西。一开始我对它感到困惑,但当你想到它时,你只是在检查等式,不管是否有实际的值/引用。因此,如果一方有效,另一方无效,那么它们在技术上是不相等的。我还看到,在一些条件中,您只检查左手操作数的HasValue,而不是右手操作数。这是我认为我做得太过分了的一些详细内容,因为之前的检查已经可以确定
    rhOp.Num2.HasValue
    (或Num3)是否已经通过。有时候能有第二双眼睛是件好事。
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, Nothing, Nothing)) = True)
    
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, True, Nothing)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, Nothing, True)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, True, True)) = False)
    
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, False, Nothing)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, Nothing, False)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, Nothing), New MyObj(True, False, False)) = False)
    
        Debug.Assert(CheckEquals(New MyObj(True, True, Nothing), New MyObj(True, True, Nothing)) = True)
        Debug.Assert(CheckEquals(New MyObj(True, True, Nothing), New MyObj(True, True, True)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, True, Nothing), New MyObj(True, True, False)) = False)
    
        Debug.Assert(CheckEquals(New MyObj(True, True, Nothing), New MyObj(True, Nothing, True)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, True, Nothing), New MyObj(True, Nothing, False)) = False)
    
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, True), New MyObj(True, Nothing, True)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, Nothing, True), New MyObj(True, Nothing, False)) = False)
        Debug.Assert(CheckEquals(New MyObj(True, True, True), New MyObj(True, True, True)) = True)
        Debug.Assert(CheckEquals(New MyObj(True, True, False), New MyObj(True, True, False)) = True)
        Debug.Assert(CheckEquals(New MyObj(True, False, False), New MyObj(True, False, False)) = True)
        Debug.Assert(CheckEquals(New MyObj(True, False, True), New MyObj(True, False, True)) = True)