I have upgraded some VB6 code, which uses fixed length strings in custom types, to VB .NET by using the UpgradeWizard and am having trouble with the use of the LSet method that I was hoping someone could help me out with.
The Existing VB6 code (type declarations);
Public Type MyType
PROP1 As String * 15
PROP2 As String * 25
End Type
Public Type MyTypeBuffer
Buffer As String * 40
End Type
Example usage;
LSet instOfMyTypeBuffer.Buffer = ...
LSet instOfMyType = instOfMyTypeBuffer
What would be an appropriate way to upgrade this to .NET?
Using the UpgradeWizard, I get the following;
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
_
Public Structure MyType
<VBFixedString(15),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr,SizeConst:=15)> _
Dim PROP1 As FixedLengthString
<VBFixedString(25),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr,SizeConst:=25)> _
Dim PROP2 As FixedLengthString
Public Shared Function CreateInstance() As MyType
Dim result As New MyType
result.PROP1 = New FixedLengthString(15)
result.PROP2 = New FixedLengthString(25)
Return result
End Function
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
_
Public Structure MyTypeBuffer
<VBFixedString(CLVHDR_REC_LENGTH),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr,SizeConst:=40)> _
Dim Buffer As FixedLengthString
Public Shared Function CreateInstance() As MyTypeBuffer
Dim result As New MyTypeBuffer
result.Buffer = New FixedLengthString(40)
Return result
End Function
End Structure
FixedLengthString is coming from the namespace Microsoft.VisualBasic.Compatibility.VB6.
Where the Upgrade Wizard fails is when it comes to LSet. It produced the following;
instOfMyTypeBuffer.Buffer = LSet(...)
instOfMyType = LSet(instOfMyTypeBuffer)
Which fails to compile, giving these errors;
Value of type 'String' cannot be converted to 'Microsoft.VisualBasic.Compatibility.VB6.FixedLengthString'
Argument not specified for parameter 'Length' of 'Public Function LSet(Source As String, Length As Integer) As String'
Value of type 'MyTypeBuffer' cannot be converted to 'String'
So, I can use ToString() to get part of the way there, but there is still the issue of the LSet method call itself. What should I do to recreate the original functionality? Has the Upgrade Wizard given me a totally inappropriate conversion, or is it salvageable into something usable?
LSet is a rather quirky statement in VB6: see description in the manual.
It's being used in a particularly quirky way in the code you have.
LSet instOfMyTypeBuffer.Buffer = ...
This is redundant both in the VB6 and the migrated Vb.Net. When you assign a new value to a fixed-length string, it always pads out with spaces anyway!
So just change to this (in either VB6 or VB.Net)
instOfMyTypeBuffer.Buffer = ...
LSet instOfMyType = instOfMyTypeBuffer
More interesting. This copies the memory from an instance of one type into an instance of another type, with no checks. Gulp!
Looking at the definitions of the types, I think this simply puts the first 15 characters from
instOfMyBuffer
intoinstOfMyType.PROP1
and the remaining 25 characters intoinstOfMyType.PROP2
.I have occasionally seen this used as an ugly way of processing fixed-length string records read from a file. For example the first fifteen characters might be a person's first name, and the next 25 the last name.
You could just replace with this code (in either VB6 or VB.Net).
instOfMyType.PROP1 = Left(instOfMyBuffer.Buffer, 15)
instOfMyType.PROP2 = Mid(instOfMyBuffer.Buffer, 16)
Hans suggested ditching the fixed-length strings. If that's easy - and it depends on the rest of your code base, it might be easy, or it might be hard - it's good advice.