Reputation: 7479
I have this code:
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)),
Nothing)
when srcCell.CELL_VALUE_FLOAT is Nothing it mysteriously evaluates to the True part!
Funny part is that a normal If statement correctly evaluates to the False part:
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
Any ideas?
Thank u!
EDIT: CELL_VALUE_FLOAT is a Nullable(Of Double) and CELL_VALUE_INT is a Nullable(of Integer)
In Quickwatch the condition evaluates correclty to False, but when running the If() function evaluates to the True part.
Upvotes: 6
Views: 7264
Reputation: 31733
Nothing
in VB.NET is not fully equal to null
in C#
It is more like default(T)
where T is a Type.
' 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
And
dim x as Double = nothing ' x will be 0 (default for Double)
the build in inline if expects both return values to be the same type. So what you a really doing is:
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)),
Convert.ToDouble(Nothing))
since the false part gets internally converted to double
and dstCell.CELL_VALUE_INT
will be 0 instead of nothing.
Try this one:
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Ctype(Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)), Integer?),
Nothing)
Upvotes: 4
Reputation: 172280
when srcCell.CELL_VALUE_FLOAT is Nothing it mysteriously evaluates to the True part!
Nope, it does not. It just evalues the false part (Nothing
) as 0
, thus setting CELL_VALUE_INT
to 0.
Let me elaborate: The expression
Dim i As Integer? = If(False, 1, Nothing)
fills i
with 0
. (Test it, if you don't believe me.)
Why does this happen? Nothing
in VB.NET is not the same as null
in C#. If used with a value type, Nothing
means "the default value of that type". If
infers Integer
(not Integer?
) as the common type for 1
and Nothing
, and, thus, evaluates Nothing
as default(Integer) = 0
.
You can fix this as follows:
Dim i As Integer? = If(False, 1, DirectCast(Nothing, Integer?))
which, in your example, would mean
dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing,
Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)),
DirectCast(Nothing, Integer?))
This should yield the correct value now.
Since this is quite surprising behaviour, I have filed a Microsoft Connect suggestion some time ago to add a compiler warning.
Upvotes: 10
Reputation: 460158
Assuming that your value is a Single
(Float):
The default value of Single
is 0 not Nothing
.
You can use a Nullable(Of T)
if you want to check for null values.
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))
Upvotes: 0