WARNING #1049

    Use of Null/IsNull() detected.

    Description

    In Visual Basic 6.0, the Null keyword indicated that a field contained no valid data, and the IsNull function was used to test for Null. In addition, Visual Basic 6 supported Null propagation when Null was used in an expression, the result of the expression would also be Null. For a more thorough discussion of data types in Visual Basic please refer to the Data Type documentation.

    Recommendations

    In Visual Basic .NET, the Null keyword is still a reserved word, but it has no syntactical value, and the IsNull function is no longer supported.

    C# also reserves the null keyword, but it is not to be confused with Null in Visual Basic 6. Visual Basic's Null keyword indicated missing or invalid data in data field, which is the purpose of DbNull in the .Net Framework. C#'s version of null is closer to Visual Basic 6's Nothing keyword.

    Also, Null propagation is no longer supported in the .NET framework. When upgrading Visual Basic 6 applications avoid null propagation.

    During upgrade, Null is converted to DBNull, and IsNull is converted to IsDBNull of which there are several variants: Visual Basic's IsDBNull function, the Convert.IsDBNull method, the DataTableReader.IsDBNull method, and the IDataRecord.IsDBNull method).

    The behavior of DBNull is slightly different than that of Null. Null could be used in functions and assignments as a Variant data type, however DBNull is a class and thus cannot be used as a direct replacement for Visual Basic's Null, DBNull.Value however can be passed as a value type in methods or assignments.

    Where Null was used with a Variant data type, the Variant is converted to Object during upgrade; in these cases, depending on context, it may be more appropriate to use the Nothing and the IsNothing function for VB.Net. For C# use the null keyword and compare with null with the equality operators (== and !=).

    Sample VB6

    Private Sub NullPropagation()
       Dim result As Variant
       Dim resultText AsString
       Dim varRight AsVariant
       Dim varLeft AsVariant
    
       ' Regular use of Left, Mid, Right
       varRight = "Hello world"
       result = Mid(varRight, 7, 5)
       resultText = resultText & "Mid(" & ResultTxt(varRight) & ", 7, 5) = " & ResultTxt(result) & vbCrLf & vbCrLf
    
       ' Null propagation 
       ' Trimming of numeric values using Left, Mid, Right
       varLeft = 20
       varRight = 10913857
       result = varLeft + Mid(varRight, 2, 5)
       resultText = resultText & ResultTxt(varLeft) & " + Mid(" & ResultTxt(varRight) & ",2 ,5) = " & ResultTxt(result) & vbCrLf
       varRight = Null
       result = varLeft + Mid(varRight, 2, 5)
       resultText = resultText & ResultTxt(varLeft) & " + Mid(" & ResultTxt(varRight) & ", 2, 5) = " & ResultTxt(result) & vbCrLf & vbCrLf
    
       ' Null propagation with + operator
       varLeft = Null
       varRight = 45298301
       result = varLeft + Left(varRight, 5)
       resultText = resultText & ResultTxt(varLeft) & " + Left(" & ResultTxt(varRight) & ", 5) = " & ResultTxt(result) & vbCrLf
       varLeft = "18205023"
       result = varLeft + Left(varRight, 5)
       resultText = resultText & ResultTxt(varLeft) & " + Left(" & ResultTxt(varRight) & ", 5) = " & ResultTxt(result) & vbCrLf & vbCrLf
    
       ' Null propagation with & (Concatenation) operator
       result = varLeft & varRight
       resultText = resultText & ResultTxt(varLeft) & " & " & ResultTxt(varRight) & " = " & ResultTxt(result) & vbCrLf
       MsgBox (resultText)
    EndSub
    
    Private Function ResultTxt(var AsVariant)
       If IsNull(var) Then
          ResultTxt = "Null"
       Else If TypeName(var) = "Integer"Or TypeName(var) = "Double"Or TypeName(var) = "Long" Then
          ResultTxt = CStr(var)
       Else
           ResultTxt = """" & var & """"
       End If
    End Function
    

    Target VB.NET

    Private Sub NullPropagation()
       Dim resultText AsString = ""
       Dim varLeft AsString = CStr(20)
    
       ' Regular use of Left, Mid, Right
       Dim varRight AsString = "Hello world"
       Dim result AsString = varRight.Substring(6, Math.Min(varRight.Length, 5))
       resultText = resultText & "Mid(" & ResultTxt(varRight) & ", 7, 5) = " & ResultTxt(result) & Strings.Chr(13) & Strings.Chr(10) & Strings.Chr(13) & Strings.Chr(10)
    
       ' Null propagation
       ' Trimming of numeric values using Left, Mid, Right
       varRight = CStr(10913857)
       result = varLeft & varRight.Substring(1, Math.Min(varRight.Length, 5))
       resultText = resultText & ResultTxt(varLeft) & " + Mid(" & ResultTxt(varRight) & ",2 ,5) = " & ResultTxt(result) & Strings.Chr(13) & Strings.Chr(10)
       'UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
       varRight = DBNull.Value
       result = varLeft & varRight.Substring(1, Math.Min(varRight.Length, 5))
       resultText = resultText & ResultTxt(varLeft) & " + Mid(" & ResultTxt(varRight) & ", 2, 5) = " & ResultTxt(result) & Strings.Chr(13) & Strings.Chr(10) & Strings.Chr(13) & Strings.Chr(10)
    
       ' Null propagation with + operator
       'UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
       varLeft = DBNull.Value
       result = varLeft & varRight.Substring(0, Math.Min(varRight.Length, 5))
       resultText = resultText & ResultTxt(varLeft) & " + Left(" & ResultTxt(varRight) & ", 5) = " & ResultTxt(result) & Strings.Chr(13) & Strings.Chr(10)
       varLeft = "18205023"
       result = varLeft & varRight.Substring(0, Math.Min(varRight.Length, 5))
       resultText = resultText & ResultTxt(varLeft) & " + Left(" & ResultTxt(varRight) & ", 5) = " & ResultTxt(result) & Strings.Chr(13) & Strings.Chr(10) & Strings.Chr(13) & Strings.Chr(10)
    
       'Following statement will throw an error Left$ will not take Null
       'result = varLeft + Left$(varRight, 5)
    
       ' Null propagation with & (Concatenation) operator
       result = varLeft & varRight
       resultText = resultText & ResultTxt(varLeft) & " & " & ResultTxt(varRight) & " = " & ResultTxt(result) & Strings.Chr(13) & Strings.Chr(10)
       MessageBox.Show(resultText, Application.ProductName)
    EndSub
    
    PrivateFunction ResultTxt(ByRef varRight AsString) AsString
       'UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
       'UPGRADE_WARNING: (1041) TypeName has a new behavior.
       If Convert.IsDBNull(varRight) Then
          Return"Null"
       Else If varRight.GetType().Name = "Integer"Or varRight.GetType().Name = "Double"Or varRight.GetType().Name = "Long"Then
          Return varRight
       Else
          Return"""" & varRight & """"
       End If
    End Function
    

     

    Expected C#

    Code that uses Null propagation requires considerable work in either the migrated version or the original VB6 code to remove such propagation.

    One approach if the affected code is small is to preface it with an If statement checking for DBNull values, as done in the sample code. Another approach if using a typed DataSet is to take advantage of the built-in IsFieldNameNull() methods to determine if a particular field is set to DBNull.Value. Alternatively, one may use the IsNull() method for DataRows to test if a particular field is DBNull.

    Another approach is to create a function that wraps this logic. That's the approach taken with the ResultTxt function which handles the output of DBNulls for us (as well as the display of strings with quotes around them).

    In this example, the input sample was limited and given C# strong-type nature we're forced to contemplate many more scenarios in code than with Visual Basic.Net's more dynamic typing. In the solution for this sample reduced the input types to System.Int32 to keep code brief.

    Additionally, two methods were created VbLeft and VbMid to replicate the behavior of the original VB functions. The reason for doing this is because the String.Substring is much more stringent about the parameters it takes and bound checks them, throwing an exception if any of them are out of bounds. Visual Basic 6 automatically handled these out of range cases.

    C#'s behavior is helpful though in highlighting possible problem areas. So another solution might involve dynamically changing the trim size based on the input. In this case C#'s strongly-type system require we pay more attention to the intent of the code and fix it accordingly.

    private string VbMid(string value, int start, int length)
    {
       length = (length > value.Length) value.Length - (start - 1) : length;
       if(value.Length > start)
       {
          return value.Substring(start - 1, length);
       }
          return string.Empty;
       }
    
    private string VbLeft(object value, int length)
    {
       if (value == null || DBNull.Value.Equals(value))
       {
          return string.Empty;
       }
       else
       {
          string temp = value.ToString();
          if (temp.Length > length)
       {
          return temp.Substring(0, length);
       }
       else return temp;
       }
    }
    
    private void NullPropagation()
    {
       string resultText = String.Empty;
    
       // Regular use of Left, Mid, Right
       object varRight = "Hello world";
       object result = VbMid(varRight.ToString(), 7, 5);
       resultText = resultText + "Mid(" + ResultTxt(varRight) + ", 7, 5) = " + ResultTxt(result) + "\r\n" + "\r\n";
    
       // Null propagation
       // Trimming of numeric values using Left, Mid, Right
       object varLeft = 20;
       varRight = 10913857;
       result = (int)varLeft + Convert.ToInt32(VbMid(varRight.ToString(), 2, 5));
       resultText = resultText + ResultTxt(varLeft) + " + Mid(" + ResultTxt(varRight) + ",2 ,5) = " + ResultTxt(result) + "\r\n";
       //UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
       varRight = DBNull.Value;
       int intLeft = (varLeft isint) (int)varLeft : 0;
       // Check for DBNull
       object tempRight = (DBNull.Value.Equals(varRight)) 0 : varRight;
       int intRight = (tempRight isint) (int)tempRight : 0;
       result = intLeft + intRight;
       resultText = resultText + ResultTxt(varLeft) + " + Mid(" + ResultTxt(varRight) + ", 2, 5) = " + ResultTxt(result) + "\r\n" + "\r\n";
    
       // Null propagation with + operator
       //UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
       varLeft = DBNull.Value;
       varRight = "45298301";
       result = varLeft + VbLeft(varRight, 5);//.Substring(0, Math.Min(varRight.Length, 5));
       resultText = resultText + ResultTxt(varLeft) + " + Left(" + ResultTxt(varRight) + ", 5) = " + ResultTxt(result) + "\r\n";
       varLeft = "18205023";
       result = varLeft + VbLeft(varRight, 5);//.Substring(0, Math.Min(varRight.Length, 5));
       resultText = resultText + ResultTxt(varLeft) + " + Left(" + ResultTxt(varRight) + ", 5) = " + ResultTxt(result) + "\r\n" + "\r\n";
    
       // Null propagation with & (Concatenation) operator
       result = varLeft.ToString() + varRight.ToString();
       resultText = resultText + ResultTxt(varLeft) + " & " + ResultTxt(varRight) + " = " + ResultTxt(result) + "\r\n";
       MessageBox.Show(resultText, Application.ProductName);
    }
    
    private string ResultTxt(object var)
    {
       //UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
       //UPGRADE_WARNING: (1041) TypeName has a new behavior.
       if (Convert.IsDBNull(var))
       {
          return"Null";
       }
       else if (var is int || var is double || var is long)
       {
          return var.ToString();
       }
       else
       {
          return"\"" + var + "\"";
       }
    }
    

    Download VBUC Free Trial
    Download VBUC Now

    It's time to eradicate VB6
    ROI of eradicating VB6

    8 Proven Tips for
    Planning a Successful Migration

    8 Tips for migration