【问题标题】:Is use of Mid(), Instr(), LBound(), UBound() etc. in VB.Net not recommended?不推荐在 VB.Net 中使用 Mid()、Instr()、LBound()、UBound() 等吗?
【发布时间】:2019-12-23 11:28:00
【问题描述】:

我来自 C# 背景,但现在主要使用 VB.Net。在我看来,上述功能(和其他功能 - 例如 UCase、LCase)等是 VB6 及之前的遗留物。在 VB.Net 中使用这些函数是不受欢迎的,还是纯粹归结为个人喜好?

我个人的偏好是远离它们,但我想知道这是否只是我对 C# 的偏见。

我遇到了几个问题 - 特别是从 VB6 转换为 VB.Net 的代码,其中集合的 0 索引意味着代码中已引入错误,因此我对它们保持警惕。

【问题讨论】:

标签: vb.net vb6


【解决方案1】:

这些函数之所以存在,当然是因为它们是 VB 语言的一部分,继承自 VB 6。

但是,它们不仅仅是框架中方法的包装器,其中一些具有一些额外的逻辑,使它们在某些方面有所不同。例如,Mid 函数允许您指定字符串之外的范围,它会默默地缩小范围并返回剩余的字符串部分。如果您指定字符串之外的范围,String.Substring 方法会引发异常。

因此,这些函数不仅仅是包装器,它们代表了一种更符合 Visual Basic 的不同编程方法,您可以在函数中抛出几乎任何东西,并且几乎总能得到一些东西。在某些方面更容易,因为您不必考虑所有特殊情况,但另一方面,当您向函数提供不合理的内容时,您可能希望获得异常而不是获得结果。在调试时,如果您尽早获得异常,而不是尝试追溯错误值的来源,通常会更容易。

【讨论】:

  • 当你说“在函数中扔几乎任何东西并且几乎总是得到一些东西”时,你想到的是哪些函数?它适用于像 CDbl 这样的转换/转换功能,但不适用于我现在能想到的任何其他功能。
  • 您可以例如调用 Mid(Nothing,4,2) 并且它不会抱怨字符串不是字符串...
【解决方案2】:

这些选项是为了向后兼容。

但是,人们最好使用框架类/方法来确保一致性。
话虽如此,VB6 的函数还是很容易理解的。因此,对于有VB背景的人来说,这应该不是问题。

编辑:此外,框架类可用的一些重载可能不适用于与简单的 VB6 类似的语句。到目前为止,我不记得有任何内容 - 但我认为这可能是使用框架类/方法的更好理由。

【讨论】:

    【解决方案3】:

    会有一些特殊情况,但是,请放心,请使用 VB6 版本,除非您关心字符串是 "" 和 Nothing 之间的区别。

    我正在从事一个大型项目,其中不同的程序员使用两种方式,人们使用MyString.SubString(1) 的代码在Mid(MyString,2) 工作时被炸毁。

    此示例的两个主要错误:(也以各种方式适用于其他错误)

    (1) 字符串可以什么都不是,你必须在对其运行方法之前进行检查。 OO 表示法的限制:如果对象什么都不是,则不能调用成员方法,即使您想要“无”或(空对象)返回。即使通过对字符串使用可空/存根对象(您可以使用“”或 string.empty)来解决此问题,您仍然必须确保它们已正确初始化 - 或者,在我们的例子中 - 转换 Nothing当从我们无法控制的库调用中接收字符串时,改为 ""。

    你会得到什么都不是的字符串。 90% 的时间你会希望它表示“”。使用.SubString,您总是无需检查。使用 VB 版本,只有您关心的 10%。

    (2) 特别是Mid 示例,同样,如果您想要 2 字符字符串的 3-10 个字符,则在 90% 的情况下,您会希望看到 "" 返回,而不是让它抛出异常!事实上,您很少需要异常:您必须首先检查适当的长度并编写代码应该如何表现(通常有一个定义的行为,至少是一个数据输入错误,您不需要不想抛出异常)。

    因此,您 100% 的时间都在使用 .Net 版本进行检查,而很少使用 VB 版本。

    .Net 希望将一切都保留在面向对象的哲学中。但是字符串与大多数以微妙方式使用的对象略有不同。 MS-Basic 在制作函数时并没有考虑到这一点,只是很幸运——函数的优点之一是它们可以处理空对象。

    对于我们的项目,有人可能会问,Nothing 字符串最初是如何进入我们的流程的。但最终,一些程序员决定使用 .Net 功能意味着可以避免的服务调用、紧急错误修复和补丁。省去你自己的麻烦。

    【讨论】:

      【解决方案4】:

      我会避开他们。既然您提到了它们,听起来好像您继承了一些可能转换为 VB.NET 项目的 VB6 代码。否则,如果它是一个新的 VB.NET 项目,我认为使用 VB6 方法没有任何价值。

      我参与过一些 VB6 到 VB.NET 的转换项目。虽然我熟悉基于 0 的索引的名称和区别,但我遇到的任何代码都经过重构以使用它们的 .NET 等效项。这部分是为了保持一致性并使该项目中的 VB6 程序员熟悉该框架。但是,我发现重构的另一个好处是能够将方法调用链接在一起。

      考虑以下几点:

      Dim input As String = "hello world"
      
      Dim result As String = input.ToUpper() ' .NET
      Dim result As String = UCase(input)    ' VB6
      

      接下来你知道,我需要做更多的工作来满足其他要求。假设我需要获取子字符串并获取“hello”,这会导致代码更新为:

      Dim result As String = input.ToUpper().Substring(0, 5) ' .NET
      Dim result As String = Mid(UCase(input), 1, 5)         ' VB6
      

      哪个更清晰更容易修改?在 .NET 中,我只是将其链接起来。在 VB6 中,我必须从方法的开头开始,然后到它的末尾并添加右括号。如果它再次发生变化或者我需要删除它,在 .NET 中我只需将结尾剪掉,但在 VB6 中我需要回溯到开头和结尾。

      我认为使用 .NET 方法是有价值的,因为后来加入该项目的其他 .NET 开发人员,尤其是那些具有 C# 背景的开发人员,可以轻松上手。

      【讨论】:

      • 我实际上发现 VB6 方法更清晰,在函数列表中首先看到最终函数的一个优点是它清楚表达式的类型是什么。 “.NET”方法更容易修改,VB6 方法需要额外的选择/删除操作,但我相信这本身就证明链接比函数方法更好。特别是如果您开始使用 fnB(fnA(x)) 再次常见的函数式语言进行任何工作。
      • 我还发现 VB6 方法更清晰。我同意 AnthonyWJones 的观点。我要补充一点,使用 .NET 方法,没有经验的程序员通常认为 input.ToUpper 更改了 input 而不是创建新字符串。是的,每个人都应该知道字符串是不可变的,但这仍然是一个常见的错误。 VB6 语法更清楚地表明输入字符串不会被更改。
      • 感谢 cmets 的家伙,有趣的观点。 @MarkJ:您发布的那些链接很有帮助。我更倾向于 Joel Coehoorn 在第一个链接中的回复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多