1
votes

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?

2
If reader("field") Is DBNull.Value (...) -- If IsDbNull(reader("field")) (...)Jimi

2 Answers

1
votes

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.

2
votes

In SQL, null = null evaluates to false. This is probably the reason why equality operator is not defined for this type.

You cannot determine if something unknown is equal to something else that is unknown, making equality operator useless.

Use DBNull.Value.Equals() to determine if it is null.