我有这段代码:
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)),
Nothing)
当 srcCell.CELL_VALUE_FLOAT为Nothing 时,它会神秘地评估为True部分!
有趣的是,正常的If语句正确评估为False部分:
If (srcCell.CELL_VALUE_FLOAT IsNot Nothing) Then
dstCell.CELL_VALUE_INT = Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT))
Else
dstCell.CELL_VALUE_INT = Nothing
End If
有什么想法吗?
谢谢你!
编辑: CELL_VALUE_FLOAT是Nullable(Of Double),CELL_VALUE_INT是Nullable(整数)
在Quickwatch中,条件将correclty评估为False,但在运行时,If()函数的计算结果为True部分。
答案 0 :(得分:7)
当srcCell.CELL_VALUE_FLOAT为Nothing时,它神秘地评估为True部分!
不,它没有。它只是将错误部分(Nothing
)评估为0
,从而将CELL_VALUE_INT
设置为0。
让我详细说明:表达式
Dim i As Integer? = If(False, 1, Nothing)
使用i
填充0
。 (测试一下,如果你不相信我的话。)
为什么会这样? VB.NET中的Nothing
与C#中的null
不同。如果与值类型一起使用,Nothing
表示“该类型的默认值”。 If
推断Integer
(不是Integer?
)作为1
和Nothing
的常见类型,因此将Nothing
评估为{{1} }}
您可以按照以下方式解决此问题:
default(Integer) = 0
,在你的例子中,意思是
Dim i As Integer? = If(False, 1, DirectCast(Nothing, Integer?))
现在应该产生正确的值。
由于这是非常令人惊讶的行为,我在前一段时间提交了Microsoft Connect suggestion来添加编译器警告。
答案 1 :(得分:3)
Nothing
与C#中的null
不完全相等
它更像是default(T)
,其中T是一个类型。
' VB:
dim x as DateTime = DateTime.MinValue
If x Is Nothing then
Console.WriteLine("True")
End if
' C#
var x = DateTime.MinValue
if (x == default(DateTime))
Console.WriteLine("True");
if (x == null) ' throw a compile time error
和
dim x as Double = nothing ' x will be 0 (default for Double)
如果希望两个返回值都是相同的类型,则内联构建。所以你真正做的是:
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)),
Convert.ToDouble(Nothing))
因为false部分内部转换为double
并且dstCell.CELL_VALUE_INT
将为0而不是任何内容。
试试这个:
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Ctype(Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)), Integer?),
Nothing)
答案 2 :(得分:0)
假设您的值为Single
(浮动):
Single
的默认值为0而非Nothing
。
如果要检查空值,可以使用Nullable(Of T)
。
Dim srcCell.CELL_VALUE_FLOAT As Nullable(Of Single)
srcCell_CELL.VALUE_FLOAT = Nothing
Dim dstCell.CELL_VALUE_INT As Nullable(Of Int32) = _
(If(srcCell.CELL_VALUE_FLOAT.HasValue,
CInt(Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT))),
Nothing))