If() – is the most evil thing I saw today

In programming, there are a few things that just don’t seem to work the way you think they should. They look nice and seem like they would make your programming tasks simpler and easier to read. The .net function If() is one of those things.

However, it has a soul that was forged in the depths of Mordor. So be very careful where/when you use it. Personally, I avoid it altogether, because I am still mad at it. Here is why.

Definition:

If(<boolean condition>, <return value if true>, <return value if false>)

Consider the following example

'I queried a database and got a dataset with this datarow.  
'It has columns ID and Name.  I want to put the name into a textbox, 
'and store the ID in a form-level variable (integer)
_ID = If(IsDbNull(dataRowName("ID")), -1, CType(dataRowName("ID"), integer))
txtName.text = If(IsDbNull(dataRowName("Name")), "", dataRowName("Name").ToString())

This seems pretty simple. If the db columns are null, it seems like it should return some default values. Otherwise, I think it should return non-null values. It is much more succinct than writing a full if/else block.

If you actually test this with a blank record (null ID and null name), you will see where the evil occurs. You will get an error:

Conversion from type 'DBNull' to type 'Integer' is not valid.

It doesn’t look like there should be a problem. Right? The If() is handling it. If ID is null, then you should get a -1. How would you get a conversion error? It should not be running that code. Right?
Bzz, wrong.

The If() function evaluates each of the arguments before passing them into the function.
So, each of the arguments get evaluated:
– Arg 1: IsDbNull(dataRowName("ID")) ‘no problem
– Arg 2: -1 ‘no problem
– Arg 3: CType(dataRowName("ID"), integer) ‘Blam! Error!

You would think that it will evaluate the first argument and then only evaluate the 2nd or 3rd (not both). Wrong-o. It evaluates all three when it passes them into the function.

This has burned many programmers. I’ve been stumped by it for an hour or two before, until I cleared my head and realized what I was looking-at.

So, be warned: If() can ruin your day. Like I said, I am still too mad at it and cannot bring myself to use it.

If you want to use something more reliable, try these instead:

Public Class DBNotNull
   '===========================================================
   '     DB Return value (not null) handlers
   ' Usage: 
   '    'I already opened a DataReader named "dr" holding columns {"Name", "suffix", "age"}
   '    txtName.Text = DBNotNullStr(dr.item("Name"))
   '    txtSuffix.Text = DBNotNullStr(dr.item("Suffix"), "Mr.")
   '    txtAge.Text = CStr(DbNotNullInt(dr.item("Age"), 0))
   '===========================================================
   Public Shared Function DBNotNullStr(val As Object, _
                           Optional defaultVal As String = "") As String
       If IsDBNull(val) Then
           Return defaultVal
       Else
          Try
              return val.tostring()
          Catch
              Return defaultVal
          End Try
       End If
   End Function

   Public Shared Function DBNotNullInt(val As Object, _
                          Optional defaultVal As Integer = 0) As Integer
       If IsDBNull(val) Then
           Return defaultVal
       Else
          Try
              return val
          Catch
              Return defaultVal
          End Try
       End If
   End Function

   ' You get the idea.  You can make more like this 
   ' to handle Bool, Dec, DateTime, etc.
End Class
Advertisements

About Tim Golisch

I'm a geek. I do geeky things.
This entry was posted in .net, Errors, Lessons Learned, Programming. Bookmark the permalink.

2 Responses to If() – is the most evil thing I saw today

  1. gregsdennis says:

    Where is this If() function, and who in their right mind would create it when there’s a perfectly good if-else concept built into the .Net languages?

    • Tim Golisch says:

      It almost looks like a left-over from F#, doesn’t it? The main purpose of this function is to shorten code. I can see it being useful with a ternary operator, but more recognizable than an Iif statement. Most C/Java folks wince when they see an Iif.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s