使用SqlDataReader(即'reader')时,我在尝试检查值是否为DBNull时遇到以下错误。
没有为类型'DBNull'定义运算符'='并键入'DBNull'。
使用以下代码时:
If reader("MyColumn") = DBNull.Value Then
'...
End If
我通过调用IsDBNull()来绕过错误,我怀疑它是由于'Is'和'='之间的差异造成的。
但是,我的问题是:为什么不能使用'='运算符进行比较?
并非所有类型都适用于=
运算符。当一个类型定义各种运算符应该如何使用它的逻辑时,它被称为“运算符重载”(这无疑是有点混乱,因为它与方法重载无关,而且完全不同)。基础Object
类型不会使=
运算符重载,因此,当您创建自定义类时,它不会从=
继承Object
运算符重载。因此,只有特别重载操作员的类型才能真正使用它。例如,以下代码将无法编译:
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运算符'='未定义类型'Module1.Person'和'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
上得到这个错误的原因是因为无论出于何种原因,编写该类的开发人员选择不为它重载=
操作符。至于为什么这样,你的猜测和我的一样好。
注意,你也可以使很多其他操作员过载,这有时会很有用。但是要小心。如果你过于自由地使用运算符重载,你可能会后悔。
在SQL中,null = null的计算结果为false。这可能是没有为此类型定义相等运算符的原因。
你无法确定未知的东西是否等于其他未知的东西,使得等式算子无用。
使用DBNull.Value.Equals()
确定它是否为空。