Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behaviour of the If() statement

Tags:

vb.net

today I stumbled upon a strange behaviour of the VB.net If() statement. Maybe you can explain why it is working like it does, or maybe you can confirm that it is a bug.

So, I have a SQL database with a table "TestTable" with an int column "NullableColumn" that can contain NULL. I'd like to read out the content of this column.

So I declare a variable of type Nullable(Of Integer) for that matter, open a SqlClient.SqlDataReader for "SELECT NullableColumn FROM TestTable" and use the following code to get the content of this column:

Dim content as Nullable(Of Integer)

...

Using reader as SqlClient.SqlDataReader = ...
  content = If(reader.IsDBNull(reader.GetOrdinal("NullableColumn")), Nothing, reader.GetInt32(reader.GetOrdinal("NullableColumn")))
End Using

But after that my variable content has the value 0, not Nothing as I would have expected.

When debugging everything looks alright, so

  • reader.GetOrdinal("NullableColumn") delivers the correct ordinal position of this column (which is 0)
  • reader.IsDBNull(0) and reader.IsDBNull(reader.GetOrdinal("NullableColumn")) deliver True, since the content of this column indeed is NULL
  • If(1=2, Nothing, "Not Nothing") delivers the String "Not Nothing"
  • If(1=1, Nothing, "Not Nothing") delivers Nothing
  • reader.GetInt32(reader.GetOrdinal("NullableColumn")) throws an error, since NULL can't be converted to Integer

So, why does my variable has the value 0?

like image 815
Nostromo Avatar asked Apr 18 '13 07:04

Nostromo


2 Answers

In VB Nothing is not the same as null. The If operator must determine the type of its result based on the arguments passed to it. Nothing, of course, has no type so the only type that the If operator can return in your code is Int32. If the IsDBNull method returns true, then the If operator returns Nothing cast as Int32. In VB, Nothing returns the default value for a type. For an Int32, the default value is 0.

From MSDN on the Nothing keyword:

Nothing represents the default value of a data type. The default value depends 
on whether the variable is of a value type or of a reference type.

For non-nullable value types, Nothing in Visual Basic differs from null in C#. 
In Visual Basic, if you set a variable of a non-nullable value type to Nothing, 
the variable is set to the default value for its declared type. In C#, if you 
assign a variable of a non-nullable value type to null, a compile-time error 
occurs.

I think just a regular If would work best:

If Not reader.IsDBNull(reader.GetOrdinal("NullableColumn")) Then
    content = reader.GetInt32(reader.GetOrdinal("NullableColumn"))
End If 

Or to keep it shorter

If Not reader.IsDBNull(reader.GetOrdinal("NullableColumn")) Then content = reader.GetInt32(reader.GetOrdinal("NullableColumn"))
like image 173
Chris Dunaway Avatar answered Sep 28 '22 11:09

Chris Dunaway


But after that my variable content has the value 0, not Nothing as I would have expected.

How do you check the content value?

First of all, you should start with content.HasValue property. It should be False for your case of Nothing and True when correct value was fetched from database.

You should also get InvalidOperationException while accessing content.Value when it hasn't got value.

like image 34
MarcinJuraszek Avatar answered Sep 28 '22 11:09

MarcinJuraszek