Language
          
              
              
              Integer data types
                      A VB6 Integer variable is a 16-bit signed integer,  therefore it should be translated to 
Short under VB.NET; likewise, a VB6 Long variable is a 32-bit signed integer and  should be translated to 
Integer under VB.NET. (A VB.NET Long variable is a 64-bit signed integer.)
            
              
              
              Currency data type
                      The Currency data type isn’t supported by VB.NET;  variables of this type should be converted to 
Decimal. However, the Decimal data type has greater precision and  range than Currency, therefore you have no guarantee that math expressions  deliver the same result they do in VB6. For example, in VB6 a Currency  operation might raise an overflow, but it would be evaluated correctly under VB.NET.
            
              
              
              Variant data type
              VB.NET doesn’t support the Variant data type; all  Variant members are translated to 
Object members. In many cases, however, the two types aren’t equivalent. For example,  an Object .NET variable can’t hold the special Empty, Null, and Missing values.
        VB Migration Partner offers the option to render a  Variant variable with the special 
VB6Variant type, if a 
SetType or 
ChangeType pragma is specified.
		
NOTE: starting with version 1.52, the VB6Variant class is not officially supported.
            
              
              
              Type declaration suffixes
                      A consequence of the fact that VB.NET redefines the  meaning of Integer and Long keywords is that the meaning of type declaration  suffixes has changed too. Now a variable whose name ends with “%” is a 32-bit  integer; a variable whose name ends with “&” is a 64-bit integer; a  variable whose name ends with “@” is a Decimal variable. However, it is  recommended that you get rid of type declaration suffixes and convert them in  standard and more readable As clauses.
            
              
              
              Fixed-length strings
                      VB6 fields, local variables, and members of Type  structures can be defined as fixed-length strings, as in:
        
        Dim buffer As String * 256
        An uninitialized fixed-length string  initially contains only ASCII 0 characters; when you assign any value to it,  the value is truncated to the maximum length, or padded with spaces to the  right if shorted than the maximum length. VB.NET doesn’t support fixed-length  strings. The Microsoft.VisualBasic.Compatibility.dll assembly defines a 
FixedLengthString type which behaves like fixed-length strings, but there are significant  differences with the original VB6 type.
        VB Migration Partner maps fixed-length strings to the 
VB6FixedString type, which mimics VB6  behavior more closely:
        
        Dim buffer As VB6FixedString(256)
            
              
              
              Conversions between Date and Double types
                      VB6 allows you to use a Double variable whenever a  Date value is expected, and vice versa. This is possible because a Date value  is nothing but a Double value whose integer portion represents the number of  days elapsed since December 30, 1899 and whose fractional part represents the  time portion of the date. When converting a piece of VB6 to VB.NET such  implicit conversions must become explicit by calls to the 
ToOADate and 
FromOADate methods of the Date type:
        
        Dim dat As Date, dbl As Double
        …
        dbl = dat.ToOADate()
        dat = Date.FromOADate(dbl)
        For uniformity and readability’s sake, VB Migration  Partner generates calls to 
DateToDouble6 and 
DoubleToDate6 methods when the  original VB6 code implicitly converts a Date value to Double, or vice versa.
            
              
              
              Conversions between String and Byte arrays
                      VB6 supports implicit conversions from String to Byte  arrays, and vice versa, as in this code snippet:
        
        Dim s1 As String, s2 As String, b() As Byte
        s1 = "abcde"
        b = s1
        s2 = b
        VB.NET doesn’t support such implicit conversions and  requires explicit calls to methods of the 
System.Text.Encoding class:
        
        Dim s1 As String, s2 As String, b() As Byte
        s1 = "abcde"
        b = Encoding.Unicode.GetBytes(s1)
        s2 = Enconding.Unicode.GetString(b)
        For uniformity and readability’s sake, VB Migration  Partner generates calls to 
ByteArrayToString6 and 
StringToByteArray6 methods when  the original code implicitly converts a Byte array to a String, or vice versa.
            
              
              
              Conversions from Boolean values
                      VB6 supports implicit conversions from Boolan values  to other numeric data types. VB.NET requires that you use the appropriate  conversion operator.
        VB Migration Partner uses the 
CByte operator when converting to a Byte variable and 
CShort when converting to any other  numeric data type.
            
              
              
              VB.NET keywords
                      Several VB.NET keywords aren’t reserved words under VB6 and can be used as member names. Examples are AddHandler, Handles, Shadows, and TimeSpan. When the name of a VB6 member matches a VB.NET keyword it must be enclosed between square brackets, as in
        
        Dim [handles] As Integer
            
              
              
              Block variables
                      If Dim keyword appears inside an If, For, For Each, Do, While, or Select block, then VB2005 limits the scope of the variable to the block itself whereas VB6 makes the variable visible to the entire method:
        
        Sub Test(ByVal n As Integer)
            If n > 0 Then
                
                Dim x As Integer
                …
            Else
                …
            End If
            …
        End Sub
        VB Migration Partner automatically moves the variable declaration outside the code block:
        
        Sub Test(ByVal n As Short)
            Dim x As Short
            If n > 0 Then
                …
            Else
                …
            End If
            …
        End Sub  
            
              
              
              Auto-instancing variables
                      VB6 variables declared with the “As New” clause are  known as 
auto-instancing variables.  The key property of these variables is lazy instantiation: the object referenced  by the variable is created as soon as one of its members is referenced; if the  variable is set to Nothing, the object is re-instantiated the next time the  variable is referenced. (A side-effect of this behavior is that testing such a  variable against Nothing always returns False.) The .NET Framework  has no notion of auto-instancing variables; in fact the following VB.NET  statement
        
        Dim w As New Widget
        is just a shorthand for the following, more verbose,  declaration:
        
        Dim w As Widget = New Widget
        where it is clear that the object is instantiated when  it is declared. If you later set the variable to Nothing, no object is re-created when you reference the variable again.
        By default, VB Migration Partner translates  auto-instancing variables verbatim, therefore the original VB6 semantics is  lost and runtime errors might occur in the converted program. However, it offers  the ability to generate code that preserves the VB6 behavior and avoids subtle bugs  or unexpected exceptions. You can enable this feature by means of the 
AutoNew pragma.
            
              
              
              Auto-instancing arrays
                      In addition to individual auto-instancing variables,  VB6 also supports auto-instancing arrays, as in the following statement:
        
        Dim arr(10) As New Widget
        Each element of such an array behaves like an  auto-instancing variable. However, the “As New” clause is invalid for VB.NET  arrays, therefore VB Migration Partner drops the “New” keyword and generate a  regular array:
        
        Dim arr(10) As Widget
        It is up to the developer to correctly initialize all  the elements in the array to avoid NullReference exceptions. However, if the application relies on the auto-instancing semantics, such a fix causes the VB.NET application to behave differently from the original VB6 code. VB Migration Partner offers the ability to create a “true”  auto-instancing array, by means of the 
AutoNew pragma.
            
              
              
              Parameter default passing mechanism
                      Under VB6, method parameters are passed  by-reference if the method parameter isn’t explicitly declared with the ByVal  keyword. Under VB.NET, method parameters are passed by-value if the method  parameter isn’t explicitly declared with the ByRef keyword. Both VB Upgrade  Wizard and VB Migration Partner correctly add an explicit ByRef for parameters  that don’t specify a ByVal keyword.
        Additionally, VB Migration Partner detects parameters that unnecessarily use ByRef and can optional convert them  to ByVal parameters.
            
              
              
              Optional parameters
                      In VB6 you can include or omit the default value of an optional parameter; if you omit it, the default value for its type is assumed (0 for numeric types, “” for strings, Nothing for objects):
        
        Sub Test(ByVal Optional x As Short, ByVal Optional y As String)
            
        End Sub
        VB.NET requires that the default value for a parameter be specified:
        
        Sub Test(ByVal Optional x As Integer = 0, ByVal Optional y As String = "")
            
        End Sub
            
              
              
              ParamArray parameters
              VB6 requires that ParamArray parameters be specified with an implicit ByRef keyword:
        
        Sub Test(ParamArray arr() As Variant)
            
        End Sub
        By contrast, VB.NET requires that an explicit ByVal keyword be specified:
        
        Sub Test(ByVal ParamArray arr() As Object)
            
        End Sub
This detail makes the difference if the method  modifies one of the elements of the parameter and some code  relies on the fact that the argument is modified,  as in this code:
    
    Sub Increment(ParamArray arr() As Variant)
        Dim i As Integer
        For i = 0 To UBound(arr)
            arr(i) = arr(i) + 1
        Next
    End Sub
    
    Sub Main()
        Dim n As Variant
        n = 10
        Increment n
        Debug.Print n   
    End Sub
After the migration to VB.NET, individual values  passed to a ParamArray parameter are passed by value, therefore any change  inside the method isn’t propagated back to the caller.
    
    Sub Increment(ByVal ParamArray arr() As Object)
        Dim i As Short
        For i = 0 To UBound(arr)
            arr(i) = arr(i) + 1
        Next
    End Sub
    
    Sub Main()
        Dim n As Object
        n = 10
        Increment(n)
        Debug.WriteLine(n)  
    End Sub
VB Migration Partner copes with this issue in two  ways. First, it makes you aware of the potential problem  by emitting a warning if any element of a ParamArray vector is modified inside  the method; second, it provides a pragma that allows you to generate  an overload of the method that doesn’t suffer from the issue.
            
              
              
              Assignments between arrays
                      When you assign an array to another array variable  under VB6, a 
copy of the source array  is assigned to the target variable. If you later modify either the source or the target array, the other array isn’t affected. VB.NET arrays are reference  types, therefore assignment between arrays are resolved internally by just assigning  the target variable a 
pointer to the  source array. If you later modify either array, the other array is modified.
        
        Dim a(10) As Integer
        Dim b() As Integer
        b = a           
        a(0) = 999      
        MsgBox b(0)     
        VB Migration Partner solves this problem by invoking  the destination array’s 
Clone method:
        
        targetArray = sourceArray.Clone()
            
              
              
              Assignments between Structures
                      Both VB6’s Type blocks and VB.NET Structure blocks are  value types; this implies that when you assign a Structure to a variable of  same type, then a 
copy of the entire  structure is assigned. If you later modify either the destination or the target  Structure, then the other Structure isn’t affected in any way. However, in  VB.NET there’s a caveat: if the Structure contains one or more arrays or  fixed-length strings, then the target Structure shares a reference to these  arrays or fixed-length strings. For example, consider the following code:
        
        Structure TestUDT
            Public Names() As String
            Public Location As VB6FixedString
        End Structure
        
        Dim source As TestUDT
        ReDim source.Names(10)
        source.Location = "Italy"
        
        Dim dest As TestUDT = source
        
        source.Names(1) = "Code Architects"
        
        Debug.WriteLine(dest.Names(1))         
        To have Structure assignments behave exactly as in VB6, if a Structure includes arrays or fixed-length strings then VB Migration Partner expands the Structure definition with a Clone method that returns a distinct copy of the Structure. All assignments between Structures of such types are then modified to call the Clone method:
        
        
        Dim dest As TestUDT = source.Clone()
            
              
              
              Structure initialization
              If you declare a VB6 Type variable, all the elements in the Type are correctly initialized; a VB.NET Structure can include neither a default constructor nor field initializers, therefore a Structure variable that has been just declared can have one or more uninitialized fields. For example, consider the following VB6 Type block:
        
        Type TestUDT
            n As Integer
            s As String * 10
            a(10) As String
            w As New Widget
        End Type
        and now consider the corresponding VB.NET Structure:
        
        Structure TestUDT
            Public n As Integer
            Public s As VBFixedString
            Public a() As String
            Public w As Widget
            
            Public Sub InitializeUDT()
                s = New VBFixedString(10)
                ReDim a(10)
                w = New Widget
            End Sub
        End Structure
        The InitializeUDT method is necessary because .NET Structures can’t have constructors with zero arguments or field initializers. The Upgrade Wizard requires that you manually invoke the InitializeUDT method to ensure that a structure variable be correctly initialized before being used:
        
        Dim udt As TestUDT
        udt.InitializeUDT    
        VB Migration Partner frees you from the need to manually initialize the structure, because it generates a constructor with one (dummy) parameter and automatically invokes this constructor whenever the application defines a structure variable that requires this treatment:
        
        Structure TestUDT
            Public n As Integer
            Public s As VBFixedString
            Public a() As String
            Public w As Widget
            Public Sub InitializeUDT()
                s = New VBFixedString(10)
                ReDim a(10)
                w = New Widget
            End Sub
            Public Sub New(ByVal dummy As Boolean)
                InitializeUDT()
            End Sub
        End Structure
        
        
        Dim udt As New TestUDT(True)
            
              
              
              Method calls
                      VB.NET requires that the list of arguments passed to a Sub method be always enclosed in parenthesis; in VB6 only calls that return a value require that argument list be enclosed in parenthesis:
        
        TestSub(12, "abc")
            
              
              
              Late-bound method calls
              VB.NET supports late-bound calls, but requires that  the 
Option Strict Off directive be  declared at the project-level or at the top of current file.
        VB Migration Partner declares Option Strict Off at the top of each file. After the migration process you should attempt to drop these statements where possible, adjusting the code in the file as necessary.
            
              
              
              Fields passed by reference to a method
                      Consider the following VB6 code, inside the Widget class:
        
        Public ID As String
        
        Public Function GetString() As String
            Dim widget As New Widget
            widget.ID = "abcde"
            TestMethod widget.ID
            GetString = widget.ID
        End Function
        
        Sub Test(ByRef text As String)
            text = UCase(text)
            …
        End Sub
        Invoking the 
GetString method under VB6 delivers the  result “abcde”, which demonstrates that the ID field has been passed to Test  method using by-value semantics even if the receiving 
text parameter is declared with the ByRef keyword. This behavior can be explained by knowing that a VB6 field is actually compiled as a Property Get/Let pair and therefore the 
Test method is actually receiving the result of the call to the “setter” block, not the actual field.
        When this code is converted “as-is” to VB.NET, the ID field is uppercased on return from the Test method, which proves that VB.NET differs from VB6 in how fields are handled.
        VB Migration Partner detects the potential bug and emits code that enforces the by-value semantics. The Upgrade Wizard converts the code as-is and doesn’t emit a warning in this case.
            
              
              
              Uninitialized local variables
                      If a local variable of reference type – that is, a  String or Object variable – is declared and not immediately initialized, the VB.NET  compiler emits the following warning:
        
        Variable 'varname' is used before it has been assigned a value. 
        A null reference exception could result at runtime.
        To avoid this warning you should initialize the  variable within the Dim statement:
        
        Dim text As String = ""
        Dim obj As Object = Nothing
            
              
              
              References to methods defined in modules
                      If code inside a VB6 form invokes a method defined in  a BAS module and the base System.Windows.Forms.Form class exposes a public or  protected method with same name, then a compilation error occurs (if the two  methods have different syntax) or, worse, the program might not work as  intended and possibly throw unexpected exceptions at runtime. For example,  suppose that the following statements are located inside a VB6 form:
        
        
        PerformLayout(False)
        ProcessKeyDialog("x"c)
        The 
PerformLayout method is exposed by the .NET System.Windows.Forms.Form  class, but it has a different syntax and therefore it is marked under VB.NET as  a compilation error. The 
ProcessKeyDialog method is also exposed by the .NET  Form class and it takes a character as an argument. Consequently, the form’s 
ProcessKeyDialog method is invoked instead of the method defined in the Helpers.bas module,  which surely causes a malfunctioning. In both cases, you can resolve the  ambiguity by prefixing the method with the module’s name (VB Migration Partner  applies this fix):
        
        Helpers.PerformLayout(False)
        Helpers.ProcessKeyDialog("x")
        VB Migration Partner detects method calls that are ambiguous and generates code that behaves as intended.
            
              
              
              Event handlers
                      In VB6 a method that handles an event must follow the 
object_eventname naming convention. In VB.NET  event handlers can have any name, provided that they are marked with an  opportune 
Handles clause:
        
        Private Sub NameClickHandler(ByVal sender As Object, ByVal e As EventArgs) _
            Handles txtName.Click
            
        End Sub
        Notice that the Handles clause for events raised by  the form itself must reference the MyBase object:
        
        Private Sub FormClickHandler(ByVal sender As Object, ByVal e As EventArgs) _
            Handles MyBase.Click
            
        End Sub
            
              
              
              Name collisions for Type…End Type blocks
                      In VB6 it is legal to have a private Type…End Type block with same name as a public class or as a Declare method defined elsewhere in the project. When the code is converted to VB.NET, the Structure that corresponds to the original Type must be renamed to avoid these name collisions.
            
              
              
              Sub Main
                      When a Sub Main method is converted to VB.NET it  should be decorated with an 
STAThread attribute:
        
        <STAThread()> _
        Public Sub Main()
            
        End Sub
            
              
              
              Member shadowing
                      A method, property, or event defined in a VB6 form  might coincidentally have same name as a member exposed by the  System.Windows.Forms.Form class, for example:
        
        Sub PerformLayout(ByVal refresh As Boolean)
            
        End Sub
        When this code is converted and compiled under VB.NET  a warning occurs, because the .NET Form class exposes a method named 
PerformLayout. To make the compiler  happy you should add a Shadows keyword:
        
        Shadows Sub PerformLayout(ByVal refresh As Boolean)
            
        End Sub
        VB Migration Partner automatically applies this fix  when necessary.
            
              
              
              Null propagation
                      VB6 Variant variables can hold the special Null value,  but no corresponding value exists in VB.NET. What makes matters worse is that  several VB6 functions – namely Str, Hex, Oct, CurDir, Environ, Chr, LCase,  UCase, Left, Mid, Right, Trim, RTrim, LTrim, and Space – support null  propagation, as the following VB6 code demonstrates:
        
        Dim var As Variant
        var = Null
        var = var + 10        
        var = Left(var, 1)    
        A Null value is neither True nor False, therefore when  the test condition of an If block is evaluated as Null, then the Else blocks is  always executed; prefixing the expression with the Not operator doesn’t  transform the expression into a non-Null value. You often need to manually  fixing converted VB6 code that relies on the peculiar way in which VB6 deals  with Null values.
        A Null value is often the result of a read operation  from a database field that contains the NULL value. When converted to VB.NET,  the actual value stored in the variable is 
DBNull.Value,  but the two values aren’t equivalent. For example, an exception is thrown at  runtime if the test condition in an If statement evaluates to DBNull.Value,  whereas no runtime error occurs in VB6 if the test condition of an If statement  evaluates to Null.
        VB Migration Partner offers a partial solution to the  null propagation problem thanks to the special 
VB6Variant type and the 
NullSupport pragma.
            
              
              
              Enum member names
                      VB6 allows you to use virtually any character inside  the name of an Enum member. If the name isn’t a valid Visual Basic identifier  you just need to enclose the name inside square brackets:
        
        Public Enum Test
            [two words]          
            [dollar$ symbol]     
            [3D]                 
            [New]                
        End Enum
        VB.NET forbids Enum member’s names that start with a  digit or contain spaces or other symbols. VB.NET does support square brackets  in Enum names, but they only allow to define names that match a language’s  keyword.
        VB Migration Partner handles this situation by  replacing invalid characters with underscores and using a leading underscore if  the first character is a digit:
        
        Public Enum Test
            two_words
            dollar__symbol]
            _3D
            [New]
        End Enum
            
              
              
              References to enum members
                      In VB6 the name of an enum member is considered as a global name. For example, you can reference members of the ColorConstants enum type with or without including the enum name:
        
        txtName.BackColor = ColorContants.vbYellow
        txtName.BackColor = vbYellow
        In VB.NET the name of the enum type can’t be omitted, therefore only the first syntax form is valid.
            
              
              
              Date variables in For…Next loops
                      VB6 supports Date variables as controlling variables in For…Next loops:
        
        Dim d As Date
        For d = Date To Date + 10
            
        Next
        Date variables can’t be used as controlling variables in VB.NET For…Next blocks, therefore VB Migration Partner converts the above code by using an “alias” variable of type Double:
        
        Dim d As Date
        For d_Alias As Double = DateToDouble6(Date) To DateToDouble6(Date + 10)
            d = DoubleToDate6(d_Alias)
            
        Next
            
              
              
              Multi-dimensional arrays in For Each…Next loops
                      There is a minor difference in how elements of a  multi-dimensional array are accessed when the array appears in a For Each…Next  loop:
        
        Dim arr(10, 20) As Double
        Dim v As Variant
        For Each v In arr
            …
        Next
        Under VB6, elements are accessed in column-wise order  – that is, first all the elements of first column, then all elements in second  column, and so forth. Conversely, under VB.NET the elements are accessed in  row-wise fashion – that is, first all the elements of the first row, then all  the elements of second row, and so forth. If visiting order is significant, the  same loop delivers different results after the migration to VB.NET. 
        VB Migration Partner emits a warning when a  multi-dimensional array appears in a For Each…Next block. If you believe that  preserving the original visiting order is important, you can insert a call to  the 
TransposeArray6 method (defined  in VBMigrationPartner_Support module), which transposes array elements so that  the migrated code works as the original one:
        
        For Each v In TransposeArray6(arr)
            …
        Next
            
              
              
              File operations with UDTs
              VB6 and VB.NET greatly differ in how UDTs - Structures  in VB.NET parlance – are read from or written to files. Not only are structure  elements stored to file in a different format, but the two languages also manage  the End-of-File condition in a different way. In VB6 you can read a UDT even if  the operation would move the file pointer beyond the current file’s length; in  VB.NET such an operation would cause an exception.
        VB Migration Partner correctly handles both these  problems, by generating code that invoke alternate file-handling methods, such  as 
FileGet6 and 
FilePut6.
            
              
              
              Collections can’t be modified inside For Each…Next loops
              VB6 allows you to modify a collection inside a For Each…Next loop that iterates on the collection itself. For example, the following code works well and is indeed quite common in VB6:
        
        Dim frm As Form
        For Each frm In Forms
            Unload frm
        Next
        This code throws an exception under VB.NET, because unloading a form causes the Forms collection to change inside the loop. The simplest way to work around this problem is having the loop iterate on a copy of the collection, as in this example:
        
        Dim values As New List(Of String)
        …
        For Each item As String In New List(Of String)(values)
            …
        Next
        VB Migration Partner doesn’t generate this fix, because it is impossible to automatically detect whether the collection is indirectly modified by any method call inside the loop.
            
              
              
              DAO.DBEngine object
                      The DAO.DBEngine object is a global object, which means that VB6 application can reference its members without having to instantiate it first and that it isn’t necessary to include the class name in the method call. In practice, this means that the following VB6 method calls to the OpenDatabase method are both valid and have the same effects:
        
        Dim db1 As DAO.Database, db2 As DAO.Database
        Set db1 = DBEngine.OpenDatabase("biblio.mdb")
        Set db2 = OpenDatabase("northwind.mdb")
        VB.NET doesn’t support global objects, therefore the above statements must be converted as follows:
        
        Dim dbeng As New DAO.DBEngine
        Dim db1 As DAO.Database, db2 As DAO.Database
        Set db1 = dbeng.OpenDatabase("biblio.mdb")
        Set db2 = dbeng.OpenDatabase("northwind.mdb")
            
              
              
              ByVal keyword in method calls
                      VB6 allows you to pass an argument to a by-reference parameter using by-value semantics, by prefixing the argument with the ByVal keyword:
        
        
        CopyMethod ByVal address, arr(0), 1024
        This calling syntax can be used only with Declare methods, and is especially useful with methods whose arguments are declared As Any, because you can’t use the ByVal keyword in the declaration of “As Any” parameters. VB.NET supports neither the ByVal keyword in method call nor As Any parameters in Declare statements. 
        VB Migration Partner accounts for such ByVal keywords and generates the corresponding overload for the Declare method.
            
              
              
              Declare statements pointing to Visual Basic runtime
                      Expert VB6 developers can invoke methods defined in VB6 runtime, for example to retrieve information about variables and arrays. Code that uses methods defined in the VB6 runtime can’t be migrated to VB.NET, both because the MSVBVM60.DLL library isn’t available and because.NET variables and arrays are stored differently from VB6 and therefore the methods wouldn’t work anyway because. 
        VB Migration Partner flags Declare statements that point to VB6 runtime with an appropriate warning.
            
              
              
              Resource files
                      VB6 resource files can’t be used under VB.NET and should be converted separately. In addition to convert files to the .NET  Framework format, VB.NET applications must be able to reference resources as 
My.Resources.Xxxx elements. 
            
              
              
              Image format tests
                      VB6 developers can test the type of an image by  testing the picture’s Type property against the values of the  PictureTypeConstants enumerated type, as in:
        
        If Picture1.Picture.Type = PictureTypeConstants.vbPicTypeEMetafile Then …
        The .NET Image type doesn’t expose the Type property,  but has an equivalent property named 
RawFormat.
        Here’s how VB Migration Partner translates previous  code:
        
        If Picture1.Picture.RawFormat is System.Drawing.Imaging.ImageFormat.Emf Then …
            
              
              
              Remarks starting with three apostrophes
              Many developers like to emphasize comments by creating lines of asterisks, dashes, or apostrophes:
        
        The problem in converting this code is that any remark that starts with three apostrophes is considered as an XML comment under VB.NET, therefore this code causes a compilation warning under VB.NET.
        VB Migration Partner recognizes the problem and replaces the third apostrophe with a space: