5

我有这个代码:

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(双精度), CELL_VALUE_INT 是 Nullable(整数)

在 Quickwatch 中,条件将 correclty 评估为 False,但在运行 If() 函数时,评估为 True 部分。

4

3 回答 3

8

当 srcCell.CELL_VALUE_FLOAT 是 Nothing 它神秘地评估为 True 部分!

不,它没有。它只是将错误部分 ( Nothing) 评估为0,因此设置CELL_VALUE_INT为 0。


让我详细说明:表达式

Dim i As Integer? = If(False, 1, Nothing)

充满。i_ 0(测试一下,如果你不相信我的话。)

为什么会这样?Nothing在 VB.NET 中与null在 C# 中不同。如果与值类型一起使用,Nothing则表示“该类型的默认值”。将(not )If推断为and的常见类型,因此计算结果为.IntegerInteger?1NothingNothingdefault(Integer) = 0

您可以按如下方式解决此问题:

Dim i As Integer? = If(False, 1, DirectCast(Nothing, Integer?))

在您的示例中,这意味着

dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,   
                            Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)),   
                            DirectCast(Nothing, Integer?))  

这现在应该产生正确的值。


由于这是非常令人惊讶的行为,我前段时间提交了Microsoft Connect 建议以添加编译器警告。

于 2012-05-22T10:19:44.967 回答
4

Nothing在 VB.NET 中并不完全等于null在 C# 中它更像是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)
于 2012-05-22T10:30:18.410 回答
0

假设您的价值是Single(浮动):

的默认值为Single0 不是Nothing

Nullable(Of T)如果要检查空值,可以使用 a 。

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))
于 2012-05-22T10:07:37.523 回答