Previous | Index | Next 

[HOWTO] Deal with Null values in If statements

A common cause for runtime exceptions in the migrated .NET application is the presence of comparison operators between Variant values that happens to be Null. Variant variables are converted to Object by default, and converted VB.NET apps have their Option Strict option set to Off, therefore the VB.NET compiler doesn’t emit any error when a comparison or math operator is applied to an Object value. A similar behavior occurs when converting to C# and the UseDynamic pragma has been used.

Even if math operations on Object variables don’t cause compilation errors, they can still throw runtime exceptions if one of the operands is Nothing, Null, or more in general can’t be converted in such a way that makes the operator work correctly. The problem is especially tricky because VB6 behaves in a way that is apparently inconsistent when an expression involving Null values appears in an If condition, as in this code:

        Dim value As Variant 
        value = Null
        ' ...
        If value <> "123" Then 
            Debug.Print "Different"
        Else
            Debug.Print "Equal"
        End If

You might expect that this code displays “Different”, because Null is different from 123. Therefore you might be surprised to see that the code actually displays the “Equal” string. The reason is: if a math or comparison operator has either operand (or both) equal to Null, the operator returns Null and makes the If condition fail. In VB6 you can avoid the Null-ness of an expression by means of the IsNull function:

        ' this code works correctly even if value is Null
        If IsNull(value) Or value <> "123" Then 
            Debug.Print "Different"
        Else
            Debug.Print "Equal"
        End If

Another common VB6 technique to get rid of Null values in expressions is by transforming the value to an empty string, which you do by simply appending an empty string:

        If (value & "") <> "123" Then 
            Debug.Print "Different"
        Else
            Debug.Print "Equal"
        End If

None of these three cases work correctly after the migration, because neither VB.NET nor C# support operators on DBNull values. More precisely, the code compiles correctly, but throws an InvalidCastException error when the math or conversion operator is encountered.

You can work around this issue is to use the FixNullValue6 method defined in the VBMigrationPartner_Support module. This method returns a null string if its argument is Nothing, Null, or Empty, and returns the unmodified argument in all other cases. For example, the previous code might be re-written as follows:

        If FixNullValue6(value) <> "123" Then
            Debug.Print  "Different"
        Else
            Debug.Print  "Equal"
        End If

Another way to work around this issue is to use the Equal6, NotEqual6, LessThan6, LessEqual6, GreaterThan6, and GreaterEqual6 functions, also defined in the VBMigrationPartner_Support module. For example, the previous code might be re-written as follows:

        If NotEqual6(value, "123") Then
            Debug.Print "Different"
        Else
            Debug.Print "Equal"
        End If

The Equal6 method as defined in the VBMigrationPartner_Support module behave exactly like the <> operator and returns Null if either argument is Null. This detail ensures that the VB6 code continues to work as before.

Conversely, the .NET versions of Equal6 and the other abovementioned methods – all of which are defined in the language support library – have a slightly different behavior: when either operand is Null, by default these methods return False. If the method appears in an If expression, then execution jumps to the Else block (as it does in VB6).

Notice that these support methods don’t solve all the issues related to Null values and should be considered merely as an aid in migrating VB6 apps that make heavy use of Null values and null propagation in expressions. You should adopt these methods very carefully to avoid introducing subtle logic errors in your code.

 

Previous | Index | Next