tags:

views:

187

answers:

2

I've got the following bit of code (that another developer wrote) that I need to modify because the ExecuteProc procedure fails. (The reason why it fails isn't in the scope of this question. It's a long story) but in scope is that I'm not sure why a NullReferenceException would occur. It's in VB.NET (I'm not a VB.NET guy myself, so I'm not sure if this is something that is unique to VB.NET):

Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports System.Collections
'(...)
Public Overloads Function ExecuteProc( ByVal pvsProcName as String) As DataSet
Dim oCommand As SqlCommand
Dim oDataAdaptor As SqlDataAdapter = New SqlDataAdapter
'Other Stuff here

  Try
    oCommand = CommandGet(ConnectionGet)
    'Do some more stuff that's irrelevant
   Catch oException As Exception
    Throw oException
   Finally
    ConnectionClose(oCommand.Connection)
    oCommand.Dispose()
    oDataAdaptor.Dispose()
  End Try
End Function

I get the following warning:

Variable 'oCommand' is used before it has been assigned a value. A null reference exception could result at runtime.`

Edit: I found the answer right before I posted the question. I posted it to keep it around (I hate putting ten minutes into something to dump it willy nilly).

My subsequent question for VB.NET folks is this:

What would be the difference in the following two intializations:

Dim oCommand As SqlCommand = Nothing

And:

Dim oCommand as New SqlComand
+6  A: 

Well, the most obvious thing is that if CommandGet fails and throws an exception, oCommand won't be set - it'll still be null, so oCommand.Connection in the Finally block will throw a NullReferenceException.

In addition, I'd say:

  • There's no need for the Catch block
  • Two Using blocks (one for the command, one for the adapter) would be better IMO than explicit Try/Finally blocks

EDIT: The difference between the two solutions is simple - one creates a "dummy" command which you then ignore or dispose (but not both). The other explicitly sets a null reference, which you can check for.

I would use a third solution though - a Using block:

Using oCommand As CommandGet(ConnectionGet)
  ' All the normal stuff in here '
End Using
Jon Skeet
I had solved the issue right before I posted this question; I kept the question around just for posterity. I can't believe whoever originally wrote this code didn't compile with warnings enabled. It was one of those 'sounding' board issues where I realized the problem when I wrote the question.
George Stocker
+3  A: 

It just means that the VB.NET compiler can't tell whether the variable is initialized before it is used, because of the way your exceptions or if blocks are structured.

You can avoid the warning by explicitly initializing your variable:

Dim oCommand As SqlCommand = Nothing
Eric Nicholson