我有一个需要使用Nullable(of Double)属性进行排序的自定义类。我已经定义了这个类,并实现了iCompare。在我的代码中,我想到我已经对Null值进行了足够的检查,但我突然看到了这个错误......
Nullable对象必须有值。
......在这一行:
Return Me.SomeDouble.Value.CompareTo(CType(obj, MatrixCellData).SomeDouble.Value)
任何人都可以解释为什么会这样吗?我知道通常使用我已包含的Double.HasValue
可以轻松避免此错误。要重现的完整示例代码如下。
Namespace MyApp
Public Class MatrixCellData
Implements IComparable
Public Property SomeDouble As Nullable(Of Double)
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
If obj Is Nothing OrElse IsDBNull(obj) OrElse Not TypeOf (obj) Is MatrixCellData Then
Return 1
Else
If Not Me.SomeDouble.HasValue Then
Return -1
Else
Return Me.SomeDouble.Value.CompareTo(CType(obj, MatrixCellData).SomeDouble.Value)
End If
End If
End Function
End Class
End Namespace
打破代码......
Dim lst As New List(Of MyApp.MatrixCellData)
lst.Add(New MyApp.MatrixCellData With {.SomeDouble = 75})
lst.Add(New MyApp.MatrixCellData With {.SomeDouble = 25})
lst.Add(New MyApp.MatrixCellData With {.SomeDouble = Nothing})
lst.Sort() ' Triggers error
答案 0 :(得分:1)
如果您不使用
Declare @Dates as nvarchar(max);
--Builds up a string of dates for the last 4 months.
Set @Dates = left(datename(Month, datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)), 3) +
right(datename(year, datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)), 2) + ',' +
left(datename(Month, datefromparts(year(dateadd(month, -2, getdate())), month(getdate())-2, 1)), 3) +
right(datename(year, datefromparts(year(dateadd(month, -2, getdate())), month(getdate())-2, 1)), 2)+ ',' +
left(datename(Month, datefromparts(year(dateadd(month, -1, getdate())), month(getdate())-1, 1)), 3) +
right(datename(year, datefromparts(year(dateadd(month, -1, getdate())), month(getdate())-1, 1)), 2)+ ',' +
left(datename(Month, getdate()), 3) +
right(datename(year, getdate()), 2);
EXEC('Select *
from
(
Select
capj.cnsmr_accnt_id,
wrkgrp_nm,
max(UDEFINST_AMT) as Instlmnt,
sum(cnsmr_accnt_pymnt_amnt) as Mnth_Tot,
--Gives the Month & year (Eg Jul15)
left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2) as Month_Yr
from
dbo.cnsmr_accnt_pymnt_jrnl capj
inner join
UDEFGENERAL UG
on
capj.cnsmr_accnt_id = UG.cnsmr_accnt_id
Inner join
wrkgrp w
on
capj.wrkgrp_id = w.wrkgrp_id
where
cnsmr_accnt_pymnt_stts_cd in (5)
and cnsmr_accnt_pymnt_pstd_dt between
--Go back to the 1st day 4 months back
datefromparts(year(dateadd(month, -3, getdate())), month(getdate())-3, 1)
and
getdate()
group by capj.cnsmr_accnt_id,
left(datename(Month, cnsmr_accnt_pymnt_pstd_dt), 3) + right(datename(year, cnsmr_accnt_pymnt_pstd_dt), 2),
wrkgrp_nm) as Mnth_Tot_Tbl
pivot
(
sum(Mnth_Tot)
for
Month_Yr in (' + @Dates + ')) as Piv')
然后没有检查阻止Me.SomeDouble等于Nothing。
当您在列表中调用sort函数时,您将为每个项目至少调用一次CompareTo函数。实际上,框架会尝试将最后一项放在有序列表中的某个位置,调用看起来与此类似:
If Not Me.SomeDouble.HasValue Then
以下所有检查均为假:
(New MatrixCellData With {.SomeDouble = Nothing}).CompareTo(New MatrixCellData With {.SomeDouble = 25})
Obj不是Nothing,(Me.SomeDouble是Nothing)
这意味着您在CompareTo方法中的最后一行
If obj Is Nothing OrElse IsDBNull(obj) OrElse Not TypeOf (obj) Is MatrixCellData Then
在Me.SomeDouble为Nothing的情况下,实际上是:
Return Me.SomeDouble.Value.CompareTo(CType(obj, MatrixCellData).SomeDouble.Value)
这当然没有意义,因为Nothing没有'Value'方法或属性。
我会把它重写为
Return Nothing.Value.CompareTo(CType(obj, MatrixCellData).SomeDouble.Value)
结束功能