Previous | Index | Next 

[PRB] Changing the type of a variable causes a Type Mismatch compilation error

The SetType pragma can be used to force VB Migration Partner to change the type of a variable or argument. A common use for this pragma is changing a string variable into a StringBuilder6 variable, as shown in this article.

However, in some cases you must take some additional steps to avoid compilation errors after the migration process. For example consider the following code

        Sub Test()
            '## s.SetType StringBuilder6
            Dim s As String, i As Integer
            s = ""
            For i = 1 To 10000
                s = s + Chr(i Mod 256)
                s = ProcessString(s)
            Next
        End Sub

        Function ProcessString (text As Variant) As String
            text = Trim(text)
            AppendSpace = text
        End Function

which is converted to VB.NET as follows:

        Sub Test()
            Dim s As StringBuilder6 = ""
            Dim i As Integer
            For i = 1 To 10000
                s = s + Chr(i Mod 256)
                s = ProcessString(s)
            Next
        End Sub

        Function ProcessString(ByRef text As Object) As String
            text = Trim(text)    ' <<< InvalidCastException
            Return text
        End Function

The StringBuilder6 type supports implicit conversions to and from string, but this ability doesn’t suffice to make this code work. In fact, the assignment inside ProcessString causes a runtime exception whose message reads

        Conversion from type 'StringBuilder6' to type 'String' is not valid.

The error persists even if you use ByVal in the parameter declaration

        Function ProcessString(ByVal text As Object) As String

and disappears only of you modify the parameter type into String, as in

        Function ProcessString(ByRef text As String) As String

The problem in changing the method declaration is that it might affect how other calls to the ProcessString method are treated. The problem is: is there a safe way to work around this issue without having to carefully test the behavior of the .NET code after the migration?

The answer is yes, and it is quite simple: just include a overload of the ProcessString method that takes and returns a StringBuilder6 value. To ensure that the result is exactly the same as in the VB6 code, this overload calls the original ProcessString method:

        Function ProcessString(ByRef text As Object) As String
            text = Trim(text)
            Return text
        End Function

        Function ProcessString(ByRef text As StringBuilder6) As StringBuilder6
            Dim tmp As Object = CStr(text)
            tmp = ProcessString(tmp)    ' call the original method
            text = CStr(tmp)
            Return text
        End Function

The easiest way to add the overloaded method is including a ParseMode pragma in the original VB6 code:

        '## ParseMode Uncomment
        'Function ProcessString(ByRef text As StringBuilder6) As StringBuilder6
        '    Dim tmp As Object = CStr(text)
        '    tmp = ProcessString(tmp)    ' call the original method
        '    text = CStr(tmp)
        '    Return text
        'End Function
        '## ParseMode On
The commented code is of course different if you are converting to C#
        '## ParseMode Uncomment
        'public StringBuilder6 ProcessString(ref StringBuilder6 text) 
        '{
        '     object tmp = text.ToString();
        '     tmp = ProcessString(tmp)    // call the original method
        '     text = tmp.ToString();
        '     return text;
        '}
        '## ParseMode On

 

Previous | Index | Next