The mystery of the If () function in VB.net

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 the true part!

The funny part is that the normal If statement correctly evaluates 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?

Thanks u!

EDIT: CELL_VALUE_FLOAT is Nullable (Of Double) and CELL_VALUE_INT is Nullable (Integer)

In Quickwatch, the condition evaluates to False, but when the If () function is run, True is calculated.

+4
source share
3 answers

Nothing in VB.NET is not completely null in C # This 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) 

build inline if it expects both return values ​​to be of the same type. So what are you really doing:

 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 is internally converted to double and dstCell.CELL_VALUE_INT will be 0 instead of nothing.

Try the following:

 dstCell.CELL_VALUE_INT = If(srcCell.CELL_VALUE_FLOAT IsNot Nothing, Ctype(Math.Round(CDbl(srcCell.CELL_VALUE_FLOAT)), Integer?), Nothing) 
+3
source

when srcCell.CELL_VALUE_FLOAT doesn’t mysteriously evaluate the True part!

No, it is not. It simply evaluates the false part ( Nothing ) as 0 , while setting CELL_VALUE_INT to 0.


Let me clarify: expression

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

fills i with 0 . (Check it out if you don't believe me.)

Why is this happening? Nothing in VB.NET is not null in C #. If used with a value type, Nothing means "the default value for this type." If indicates Integer (not Integer? ) As the common type for 1 and Nothing , and thus evaluates Nothing as default(Integer) = 0 .

You can fix it as follows:

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

which in your example means

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

This should now give the correct meaning.


Since this is a pretty amazing behavior, I added some Microsoft Connect suggestion to add a compiler warning.

+7
source

Assuming your value is Single (Float):

The default value of Single is 0 not Nothing .

You can use 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)) 
0
source

Source: https://habr.com/ru/post/1413716/


All Articles