VB to .NET

TODO #1059

Code was upgraded to use 1% which may not have the same behavior.

Description

This EWI appears when a Visual Basic method call is changed to a .NET counterpart that may not have the same behavior as the original.

Recommendations

In most cases the .NET equivalents provide equivalent functionality but there can be edge cases for which its functionality differs. Most commonly VB6 performed a lot of validations and auto coercions.

Unfortunately, there is such a wide variety of cases that might cause this EWI that it would be prohibitive to list them all with possible resolutions.

It is however important to note that often times these differences can depend on the parameters passed to the methods. Thus choosing a different signature of the same method might provide the desired functionality.

Therefore, it is recommended that the migration consultant research the target and source methods to achieve the desired functionality.

Sample VB6

For example this problem can happen while migrating assignments of strings to byte arrays. Byte arrays are somewhat special because VB6 lets you directly assign strings to them.

In this case, VB6 performs a direct memory copy of the contents of the string. Because all VB5 and VB6 strings are Unicode strings (two bytes per character), the target array is re-dimensioned to account for the actual string length in bytes.  Most of the code meets functional equivalence. In some cases GAPVelocity AI own migration library is used as it more closely matches Visual Basic 6 in behavior, however for this particular case the System.Text.Encoding.Unicode.GetString and System.Text.Encoding.Unicode.GetBytes methods provide very similar functionality. The GAPVelocity AI library method StringsHelper.ByteArrayToString provides checking for edge cases where an odd number of bytes are sent thus resulting in an invalid Unicode sequence.

Public Function CoercionArrayToString(ByRef ByteArray() As Byte) As String
  CoercionArrayToString = ByteArray
End Function

 

Public Function CoercionStringToArray(ByVal ByteText As String) As Byte()
CoercionStringToArray = ByteText
End Function

Target VB.NET

Public Function CoercionArrayToString(ByRef ByteArray() AsByte) As String
'UPGRADE_TODO: (1059) Code was upgraded to use Artinsoft.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.
  Return StringsHelper.ByteArrayToString(ByteArray)
End Function

Public Function CoercionStringToArray(ByVal ByteText AsString) AsByte()
'UPGRADE_TODO: (1059) Code was upgraded to use System.Text.UnicodeEncoding.Unicode.GetBytes() which may not have the same behavior.
  Return UnicodeEncoding.Unicode.GetBytes(ByteText)
End Function

Private Sub Command1_Click(ByVal eventSender As Object, ByVal eventArgs As EventArgs) Handles Command1.Click

  ' Strings in VB6 are Unicode and take 2 bytes per character
  ' Build a byte array of byte pairs to create the alphabet
  ' and a series of double byte values (unicode)
  Dim myAlphabet(26 * 4 - 1) As Byte
  For i AsInteger = 0 To (26 * 4 - 1)
    If i Mod 2 = 0 Then
      myAlphabet(i) = 65 + (i / 2)
    Else
      If i < (26 * 2) Then
        myAlphabet(i) = 0
      Else
        myAlphabet(i) = 1
      End If
    End If
  Next
' myAlphabet now holds these values:
' "65 0 66 0 67 0 68 0 69 0 70 0 71 0 72 0 73 0 74 0 75 0 76 0 77 0 78 0 79 0 80 0 81 0 82 0 83 0 84 0 85 0 86 0 87 0 88 0 89 0 90 0"
  Dim text_Renamed AsString = LiteralArray(myAlphabet)
' Write byte values to text file, there one can better appreciate unicode chars
  WriteFile("C:\alpha.txt", myAlphabet)
' Coerce ByteArray to String through function
  Dim coercedString AsString = CoercionArrayToString(myAlphabet)
' Coerce string to array and write results to file to verify no data has been lost
  WriteFile("C:\beta.txt", CoercionStringToArray(coercedString))
' text holds literal byte representation
  MessageBox.Show(text_Renamed, Application.ProductName)
  MessageBox.Show(coercedString, Application.ProductName)
  Dim coercedBytes() AsByte = CoercionStringToArray("1 2 3 4 5 6 7")
  'UPGRADE_WARNING: (1041) LenB has a new behavior.
  text_Renamed = "1 2 3 4 5 6 7 Length: " & ("1 2 3 4 5 6 7").Length & " LenB: " & CStr(Encoding.Unicode.GetByteCount("1 2 3 4 5 6 7")) & Strings.Chr(13) & Strings.Chr(10)
  text_Renamed = text_Renamed & LiteralArray(coercedBytes)
  MessageBox.Show(text_Renamed, Application.ProductName)
'UPGRADE_TODO: (1059) Code was upgraded to use Artinsoft.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.
  MessageBox.Show(StringsHelper.ByteArrayToString(coercedBytes), Application.ProductName)
End Sub

Private Function LiteralArray(ByRef bytes() As Byte) As String

Dim text_Renamed As String = ""
For Each bytes_item As Byte In bytes
  text_Renamed = text_Renamed & CStr(bytes_item) & " "
Next bytes_item
Return text_Renamed

End Function

Private Sub WriteFile(ByRef fileName As String, ByRef bytes() As Byte)

Try
  File.Delete(fileName)
Catch
End Try
Dim fnum AsInteger
' Save the file.
fnum = FileSystem.FreeFile()
FileSystem.FileOpen(fnum, fileName, OpenMode.Binary)
'UPGRADE_WARNING: (1041) Put was upgraded to FilePutObject and has a new behavior.
FileSystem.FilePutObject(fnum, bytes, 1)
FileSystem.FileClose(fnum)

End Sub

Expected VB.NET

In this case most of the code meets functional equivalence. In some cases GAPVelocity AI own migration library is used as it more closely matches VB6 in behavior, however for this particular case the System.Text.Encoding.Unicode.GetString and System.Text.Encoding.Unicode.GetBytes methods provide very similar functionality. The GAPVelocity AI library provides checking for edge cases where an odd number of bytes are sent thus resulting in an invalid Unicode sequence.

The only correction that had to be done was to fix the auxiliary WriteFile method.

Public Function CoercionArrayToString(ByRef ByteArray() As Byte) As String

'UPGRADE_TODO: (1059) Code was upgraded to use Artinsoft.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.
Return StringsHelper.ByteArrayToString(ByteArray)

End Function

Public Function CoercionStringToArray(ByVal ByteText As String) As Byte()

'UPGRADE_TODO: (1059) Code was upgraded to use System.Text.UnicodeEncoding.Unicode.GetBytes() which may not have the same behavior.
Return UnicodeEncoding.Unicode.GetBytes(ByteText)

End Function

 

Private Sub Command1_Click(ByVal eventSender As Object, ByVal eventArgs As EventArgs) Handles Command1.Click

' Strings in VB6 are Unicode and take 2 bytes per character
' Build a byte array of byte pairs to create the alphabet
' and a series of double byte values (unicode)

Dim myAlphabet(26 * 4 - 1) AsByte
For i AsInteger = 0 To (26 * 4 - 1)
    If i Mod 2 = 0 Then
      myAlphabet(i) = 65 + (i / 2)
    Else

If i < (26 * 2) Then
   myAlphabet(i) = 0
Else
   myAlphabet(i) = 1
End If

End If

  Next

' myAlphabet now holds these values:
' "65 0 66 0 67 0 68 0 69 0 70 0 71 0 72 0 73 0 74 0 75 0 76 0 77 0 78 0 79 0 80 0 81 0 82 0 83 0 84 0 85 0 86 0 87 0 88 0 89 0 90 0"

Dim text_Renamed AsString = LiteralArray(myAlphabet)

' Write byte values to text file, there one can better appreciate unicode chars
WriteFile("C:\alpha.txt", myAlphabet)
' Coerce ByteArray to String through function
Dim coercedString AsString = CoercionArrayToString(myAlphabet)
' Coerce string to array and write results to file to verify no data has been lost
WriteFile("C:\beta.txt", CoercionStringToArray(coercedString))
' text holds literal byte representation
MessageBox.Show(text_Renamed, Application.ProductName)
MessageBox.Show(coercedString, Application.ProductName)
Dim coercedBytes() AsByte = CoercionStringToArray("1 2 3 4 5 6 7")
'UPGRADE_WARNING: (1041) LenB has a new behavior.
text_Renamed = "1 2 3 4 5 6 7 Length: " & ("1 2 3 4 5 6 7").Length & " LenB: " & CStr(Encoding.Unicode.GetByteCount("1 2 3 4 5 6 7")) & Strings.Chr(13) & Strings.Chr(10)
text_Renamed = text_Renamed & LiteralArray(coercedBytes)

MessageBox.Show(text_Renamed, Application.ProductName)
'UPGRADE_TODO: (1059) Code was upgraded to use Artinsoft.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.
MessageBox.Show(StringsHelper.ByteArrayToString(coercedBytes), Application.ProductName)

EndSub

 

Private Function LiteralArray(ByRef bytes() As Byte) As String

Dim text_Renamed As String = ""
For Each bytes_item As Byte In bytes
text_Renamed = text_Renamed & CStr(bytes_item) & " "
Next bytes_item
Return text_Renamed

End Function

Private Sub WriteFile(ByRef fileName As String, ByRef bytes() As Byte)

Try

File.Delete(fileName)

Catch

EndTry

File.WriteAllBytes(fileName, bytes)

End Sub

Target C#

public string CoercionArrayToString(byte[] ByteArray)
{

//UPGRADE_TODO: (1059) Code was upgraded to use Artinsoft.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.

return StringsHelper.ByteArrayToString(ByteArray);

}

 

public byte[] CoercionStringToArray(string ByteText)
{

//UPGRADE_TODO: (1059) Code was upgraded to use System.Text.UnicodeEncoding.Unicode.GetBytes() which may not have the same behavior.

return UnicodeEncoding.Unicode.GetBytes(ByteText);

}

 

private void Command1_Click(Object eventSender, EventArgs eventArgs)
{

// Strings in VB6 are Unicode and take 2 bytes per character
// Build a byte array of byte pairs to create the alphabet
// and a series of double byte values (unicode)

byte[] myAlphabet = new byte[26 * 4];
for (int i = 0; i <= (26 * 4 - 1); i++)
{

if (i % 2 == 0)
{

myAlphabet[i] = Convert.ToByte(65 + (i / 2d));

}

else
{

 if (i < (26 * 2))  
 {
   myAlphabet[i] = 0;
 }
 else
 {
      myAlphabet[i] = 1;
 }

}

}
// myAlphabet now holds these values:
// "65 0 66 0 67 0 68 0 69 0 70 0 71 0 72 0 73 0 74 0 75 0 76 0 77 0 78 0 79 0 80 0 81 0 82 0 83 0 84 0 85 0 86 0 87 0 88 0 89 0 90 0"
  string text_Renamed = LiteralArray(myAlphabet);
// Write byte values to text file, there one can better appreciate unicode chars
  WriteFile("C:\\alpha.txt", myAlphabet);
// Coerce ByteArray to String through function
  string coercedString = CoercionArrayToString(myAlphabet);
// Coerce string to array and write results to file to verify no data has been lost
  WriteFile("C:\\beta.txt", CoercionStringToArray(coercedString));
// text holds literal byte representation
  MessageBox.Show(text_Renamed, Application.ProductName);
  MessageBox.Show(coercedString, Application.ProductName);
  byte[] coercedBytes = (byte[])CoercionStringToArray("1 2 3 4 5 6 7");
//UPGRADE_WARNING: (1041) LenB has a new behavior.
  text_Renamed = "\"1 2 3 4 5 6 7\" Length: " + ("1 2 3 4 5 6 7").Length.ToString() + " LenB: " + Encoding.Unicode.GetByteCount("1 2 3 4 5 6 7").ToString() + "\r\n";
  text_Renamed = text_Renamed + LiteralArray(coercedBytes);
  MessageBox.Show(text_Renamed, Application.ProductName);
  //UPGRADE_TODO: (1059) Code was upgraded to use UpgradeHelpers.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.
  MessageBox.Show(StringsHelper.ByteArrayToString(coercedBytes), Application.ProductName);
}

private string LiteralArray(byte[] bytes)
{
  string text_Renamed = "";
  foreach (byte bytes_item in bytes)
  {
   text_Renamed = text_Renamed + bytes_item.ToString() + " ";
  }
  return text_Renamed;
}

private void WriteFile(string fileName, byte[] bytes)
{
  try
  {
    File.Delete(fileName);
  }
  catch
  {}

  int fnum = 0;
// Save the file.
  fnum = FileSystem.FreeFile();
  FileSystem.FileOpen(fnum, fileName, OpenMode.Binary, OpenAccess.Default, OpenShare.Default, -1);
  //UPGRADE_WARNING: (1041) Put was upgraded to FilePutObject and has a new behavior.
  FileSystem.FilePutObject(fnum, bytes, Convert.ToInt32(1));
  FileSystem.FileClose(fnum);
}

Expected C#

In this case most of the code meets functional equivalence. In some cases GAPVelocity AI's own migration library is used as it more closely matches Visual Basic 6 in behavior, however for this particular case the System.Text.Encoding.Unicode.GetString and System.Text.Encoding.Unicode.GetBytes methods provide very similar functionality. The GAPVelocity AI library provides checking for edge cases where an odd number of bytes are sent thus resulting in an invalid Unicode sequence.

The only correction that had to be done was to fix the auxiliary WriteFile method.

public string CoercionArrayToString(byte[] ByteArray)
{
//UPGRADE_TODO: (1059) Code was upgraded to use Artinsoft.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.
  return StringsHelper.ByteArrayToString(ByteArray);
}

public byte[] CoercionStringToArray(string ByteText)
{
//UPGRADE_TODO: (1059) Code was upgraded to use System.Text.UnicodeEncoding.Unicode.GetBytes() which may not have the same behavior.
   return UnicodeEncoding.Unicode.GetBytes(ByteText);
}

private void Command1_Click(Object eventSender, EventArgs eventArgs)
{

// Strings in VB6 are Unicode and take 2 bytes per character
// Build a byte array of byte pairs to create the alphabet
// and a series of double byte values (unicode)
byte[] myAlphabet = new byte[26 * 4];
for (int i = 0; i <= (26 * 4 - 1); i++)
{

if (i % 2 == 0)
{

myAlphabet[i] = Convert.ToByte(65 + (i / 2d));

}
else
{
    if (i < (26 * 2))
    {

myAlphabet[i] = 0;

}
else
{
  myAlphabet[i] = 1;

}

}

}
// myAlphabet now holds these values:
// "65 0 66 0 67 0 68 0 69 0 70 0 71 0 72 0 73 0 74 0 75 0 76 0 77 0 78 0 79 0 80 0 81 0 82 0 83 0 84 0 85 0 86 0 87 0 88 0 89 0 90 0"

string text_Renamed = LiteralArray(myAlphabet);

// Write byte values to text file, there one can better appreciate unicode chars

WriteFile("C:\\alpha.txt", myAlphabet);

// Coerce ByteArray to String through function

string coercedString = CoercionArrayToString(myAlphabet);

// Coerce string to array and write results to file to verify no data has been lost

WriteFile("C:\\beta.txt", CoercionStringToArray(coercedString));
// text holds literal byte representation

MessageBox.Show(text_Renamed, Application.ProductName);
MessageBox.Show(coercedString, Application.ProductName);

byte[] coercedBytes = (byte[])CoercionStringToArray("1 2 3 4 5 6 7");

//UPGRADE_WARNING: (1041) LenB has a new behavior.
text_Renamed = "\"1 2 3 4 5 6 7\" Length: " + ("1 2 3 4 5 6 7").Length.ToString() + " LenB: " + Encoding.Unicode.GetByteCount("1 2 3 4 5 6 7").ToString() + "\r\n";

text_Renamed = text_Renamed + LiteralArray(coercedBytes);

MessageBox.Show(text_Renamed, Application.ProductName);

//UPGRADE_TODO: (1059) Code was upgraded to use UpgradeHelpers.VB6.Utils.StringsHelper.ByteArrayToString() which may not have the same behavior.

MessageBox.Show(StringsHelper.ByteArrayToString(coercedBytes), Application.ProductName);

}

 

private string LiteralArray(byte[] bytes)
{

string text_Renamed = "";
foreach (byte bytes_item in bytes)
{

text_Renamed = text_Renamed + bytes_item.ToString() + " ";

}
return text_Renamed;

}

private void WriteFile(string fileName, byte[] bytes)
{
  try
  {
   File.Delete(fileName);
  }
  catch
  {
  }
  File.WriteAllBytes(fileName, bytes);
}

Talk To An Engineer