运算符“=”没有为类型 'DBNull' 和类型 'DBNull' 定义

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

在使用 SqlDataReader(即 'reader')时,我在尝试检查值是否为 DBNull 时遇到以下错误。

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

使用以下代码时:

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

我通过调用 IsDBNull() 绕过错误,我怀疑这是由于 'Is' 和 '=' 之间的差异造成的。

但是,我的问题是:为什么不能使用“=”运算符进行比较?

在 SQL 中,null = null 的计算结果为 false。这可能就是为什么没有为这种类型定义相等运算符的原因。

您无法确定未知事物是否等于其他未知事物,这使得相等运算符无用。

使用DBNull.Value.Equals()判断是否为空

并非所有类型都适用于 = 运算符。当一个类型定义了各种运算符应该如何使用它的逻辑时,它被称为 "operator overloading" (这确实有点令人困惑,因为它与方法重载无关,而且完全不同)。基本 Object 类型不会重载 = 运算符,因此,当您创建自定义 class 时,它不会从 [=13] 继承 = 运算符重载=].因此,只有专门重载运算符的类型才能真正使用它。例如,以下代码将无法编译:

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

编译器给出以下构建错误:

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

但是,这将按预期构建和工作:

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

所以,您在 DBNull 上出现该错误的原因是,无论出于何种原因,编写 class 的开发人员选择不为其重载 = 运算符.至于为什么会这样,你猜和我的一样好。

旁注,您也可以重载许多其他运算符,这有时很有用。但是,请小心。如果您对运算符重载的使用过于自由,您可能会后悔。

SqlDataReader class 有一个方法:SqlDataReader.IsDBNull(Int32) Method.

Dim colNum = reader.GetOrdinal("MyColumn")
If sqlReader.IsDBNull(colNum) Then
    ' Do something
End If