Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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.

like image 774
Teejay Avatar asked May 22 '12 09:05

Teejay


People also ask

What is IF statement in VB net?

Example of an If-Then statement is − If (a <= 20) Then c= c+1 End If. If the condition evaluates to true, then the block of code inside the If statement will be executed. If condition evaluates to false, then the first set of code after the end of the If statement (after the closing End If) will be executed.

What is the function of if/then else statement in Visual Basic?

When an If ... Then ... Else statement is encountered, condition is tested. If condition is True , the statements following Then are executed. If condition is False , each ElseIf statement (if there are any) is evaluated in order.

What is the syntax of if statement in VB?

Following is the If-Then-Else statement syntax in VB.NET as follows: Syntax: If (Boolean_expression) Then. 'This statement will execute if the Boolean condition is true.

What is if in Visual Basic?

In Visual Basic, If statement is useful to execute the block of code or statements conditionally based on the value of an expression. Generally, in Visual Basic, the statement that needs to be executed based on the condition is known as a “Conditional Statement” and the statement is more likely a block of code.


2 Answers

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.

like image 155
Heinzi Avatar answered Sep 28 '22 09:09

Heinzi


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)
like image 26
Jürgen Steinblock Avatar answered Sep 28 '22 08:09

Jürgen Steinblock