【问题标题】:Converting VB6 Custom Type (with Fixed Length Strings) to VB .NET将 VB6 自定义类型(具有固定长度字符串)转换为 VB .NET
【发布时间】:2010-10-05 14:08:19
【问题描述】:

我已经使用 UpgradeWizard 将一些在自定义类型中使用固定长度字符串的 VB6 代码升级到 VB .NET,并且在使用 LSet 方法时遇到了问题,我希望有人能帮助我。

现有的 VB6 代码(类型声明);

Public Type MyType
    PROP1       As String * 15
    PROP2       As String * 25
End Type

Public Type MyTypeBuffer
    Buffer As String * 40
End Type

用法示例;

LSet instOfMyTypeBuffer.Buffer = ...
LSet instOfMyType = instOfMyTypeBuffer

将其升级到 .NET 的合适方法是什么?

使用升级向导,我得到以下信息;

<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 来自命名空间 Microsoft.VisualBasic.Compatibility.VB6。

升级向导失败的地方在于 LSet。它产生了以下内容;

instOfMyTypeBuffer.Buffer = LSet(...)
instOfMyType = LSet(instOfMyTypeBuffer)

编译失败,出现这些错误;

“字符串”类型的值不能 转换成 'Microsoft.VisualBasic.Compatibility.VB6.FixedLengthString'

没有为参数指定参数 “公共职能”的“长度” LSet(源为字符串,长度为 整数)作为字符串'

“MyTypeBuffer”类型的值不能 转换为“字符串”

所以,我可以使用 ToString() 来获得其中的一部分,但仍然存在 LSet 方法调用本身的问题。我应该怎么做才能重新创建原始功能?升级向导是否给了我一个完全不合适的转换,或者它是否可以挽救成可用的东西?

【问题讨论】:

  • 这是不可挽救的,这种形式的 LSet 不再受支持,因为它会生成无法验证的代码。抛弃固定长度的字符串。
  • @Hans 你对LSet 的看法是正确的。但是在这里我认为LSet 只是被用作一种奇怪的方式来进行简单的字符串操作。我觉得很容易recode the manipulations in VB.Net
  • 我之前发布过类似的问题,可能相关:stackoverflow.com/questions/3863191/…
  • @Hans 您的其他答案在一般情况下看起来很棒。这是一种特殊情况,LSet 被滥用来分割由固定长度字符串组成的记录。
  • 谢谢汉斯,我看了看你的其他答案,效果很好。但是,正如我在对 MarkJ 答案的评论中解释的那样,我决定将代码重新编写回安全世界。感谢您的建议,我从中学到了很多。

标签: .net vb6 vb6-migration


【解决方案1】:

LSet 是 VB6 中一个相当古怪的语句:参见description in the manual

  • 当用于字符串时,它会将原始字符串中的字符串左对齐,并用空格替换任何剩余的字符。
  • 当用于用户定义类型时,它只是将内存从一种用户定义类型复制到另一种,即使它们有不同的定义。不建议这样做。

在您的代码中以一种特别古怪的方式使用它。

  1. LSet instOfMyTypeBuffer.Buffer = ...
    这在 VB6 和迁移的 Vb.Net 中都是多余的。当您为固定长度的字符串分配新值时,无论如何它总是用空格填充!
    所以只要改成这个(在 VB6 或 VB.Net 中)
    instOfMyTypeBuffer.Buffer = ...
  2. LSet instOfMyType = instOfMyTypeBuffer
    更有意思的。这会将内存从一种类型的实例复制到另一种类型的实例中,无需检查。 咕噜咕噜!
    查看类型的定义,我认为这只是将 instOfMyBuffer 中的前 15 个字符放入 instOfMyType.PROP1,其余 25 个字符放入 instOfMyType.PROP2
    我偶尔会看到这被用作处理从文件读取的固定长度字符串记录的一种丑陋方式。例如,前 15 个字符可能是一个人的名字,接下来的 25 个字符可能是姓氏。
    您可以只替换此代码(在 VB6 或 VB.Net 中)。
    instOfMyType.PROP1 = Left(instOfMyBuffer.Buffer, 15)
    instOfMyType.PROP2 = Mid(instOfMyBuffer.Buffer, 16)

Hans 建议放弃固定长度的字符串。如果这很容易 - 并且取决于您的代码库的其余部分,可能很容易,或者 可能很难 - 这是个好建议。

【讨论】:

  • 感谢您的解释 - 这是我负责迁移的遗留代码,这是我第一次体验这种数据处理。我自己做了一些研究,发现了一个 C# 解决方案; codeproject.com/KB/cs/gil_structs.aspx你认为这样的事情是否也合适?我想它仍然不是真正符合 .NET 的精神,但你认为它可以解决问题吗?
  • @C.McAtackney 很好的发现 - 我认为这可能会奏效。可能它可能需要“固定”缓冲区以阻止 .Net 框架将其部分移动?就像 Hans 在his other answer 中所做的那样。无论如何,它仍然和原始代码一样丑陋、难以理解和潜在的风险!我建议改用Left()Mid(),或.Net 等效的.Substring()
  • 我实现了 Hans 的方法并且效果很好。然后我回去仔细检查了原始代码,除了方便之外,无法想出任何其他解释来解释为什么以这种方式使用 LSet。因此,我决定实现我自己的 FixedLengthString 类和将输入字符串映射到 Dictionary 的父类型。它工作得很好,我已经包含了一些使用 String.PadRight(...) 来重新创建原始行为。感谢所有帮助,非常感谢。
  • @C.McAtackney 您自己的新课程听起来像是一个不错的干净替代品。我同意原始代码必须是用于拆分字符串缓冲区的一部分的丑陋-不可读/聪明的性能技巧。 Hans 的方法更为通用,我对他对 .Net 内部结构的了解感到敬畏,但最终在这种情况下,它只是 .Net 中的一个丑陋-不可读/聪明的性能技巧,而且风险更大,因为 .Net 移动内存大约。我不认为您的继任者会对此感到满意,在那个遥远的日子里,当您在其他地方并且代码现在是其他人的遗留代码分配时! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 2015-07-31
  • 2013-11-27
  • 2020-03-17
  • 2019-11-22
  • 2014-12-15
相关资源
最近更新 更多