Search code examples
vb.netdbnull

Operator '=' is not defined for type 'DBNull' and type 'DBNull'


While using an SqlDataReader (namely 'reader'), I encountered the following error when trying to check if a value is DBNull.

Operator '=' is not defined for type 'DBNull' and type 'DBNull'.

When using the following code:

If reader("MyColumn") = DBNull.Value Then
  '...
End If

I have circumnavigated the error by using a call to IsDBNull() and I suspect it is due to a difference between 'Is' and '='.

However, the question I have is: why is it not possible to make the comparison using the '=' operator?


Solution

  • Not all types work with the = operator. When a type defines the logic for how various operators are supposed to work with it, it's called "operator overloading" (which is admittedly a little confusing because it is unrelated, and quite different, from method overloading). The base Object type doesn't overload the = operator, so, when you create a custom class, it won't inherit the = operator overload from Object. So, only types which specifically overload the operator can actually work with it. For instance, the following code will not compile:

    Module Module1
        Public Sub Main()
            Dim dan As New Person() With {.Id = 1, .Name = "Daniel Thorne"}
            Dim steve As New Person() With {.Id = 2, .Name = "Steven Doggart"}
            If dan = steve Then
                Console.WriteLine("They're the same")
            End If
        End Sub
    
        Public Class Person
            Public Property Id As Integer
            Public Property Name As String
        End Class
    End Module
    

    The compiler gives the following build error:

    BC30452 Operator '=' is not defined for types 'Module1.Person' and 'Module1.Person'.

    However, this will build and work as expected:

    Public Sub Main()
        Dim dan As New Person() With {.Id = 1, .Name = "Daniel Thorne"}
        Dim steve As New Person() With {.Id = 2, .Name = "Steven Doggart"}
        If dan = steve Then
            Console.WriteLine("They're the same")
        End If
    End Sub
    
    Public Class Person
        Public Property Id As Integer
        Public Property Name As String
    
        Public Shared Operator =(x As Person, y As Person) As Boolean
            Return AreEqual(x, y)
        End Operator
    
        Public Shared Operator <>(x As Person, y As Person) As Boolean
            Return Not AreEqual(x, y)
        End Operator
    
        Private Shared Function AreEqual(x As Person, y As Person) As Boolean
            If (x Is Nothing) And (y Is Nothing) Then
                Return True
            ElseIf (x IsNot Nothing) And (y IsNot Nothing) Then
                Return x.Id = y.Id
            Else
                Return False
            End If
        End Function
    End Class
    

    So, the reason why you get that error on DBNull is because, for whatever reason, the developers who wrote that class chose not to overload the = operator for it. As far as why that is, you're guess is as good as mine.

    Side note, you can overload a lot of other operators too, which can sometimes be useful. However, be careful. If you are too liberal in your use of operator overloading, you'll probably come to regret it.