【问题标题】:Chance of breaking existing code by adding optional parameter to VB.NET function?通过向 VB.NET 函数添加可选参数来破坏现有代码的机会?
【发布时间】:2017-11-02 14:41:02
【问题描述】:

如果我将新的可选参数添加到随处使用的函数,是否有可能导致大型项目中的现有代码被炸毁?我知道我可以重载函数并将风险降到最低,但真的..如果我坚持使用可选参数会有什么风险?

这是一个例子:

    Public Function GetContent(ByVal URL As String, ByVal ID As String, Optional ByRef PageTitle As String = "") As String
        Try
            Dim web As New HtmlWeb()
            Dim doc As HtmlDocument = web.Load(URL)
            ID = "//div[@id='" & ID & "']"
            Dim ContentNode As HtmlNode = doc.DocumentNode.SelectSingleNode(ID)

            ' The two lines below are the mere extent of what's new inside this function, besides the new Optional ByRef parameter in its signature
            Dim PageTitleNode As HtmlNode = doc.DocumentNode.SelectSingleNode("//title")
            If Not PageTitleNode Is Nothing Then PageTitle = PageTitleNode.InnerHtml

            Return ContentNode.InnerHtml

        Catch ex As Exception
            Return "<h4> Bad. Very bad. </h4>"
        End Try
    End Function

PS:我想在事后对我的问题发表评论,阅读了下面其他人的回答并自己做了一些额外的研究。最初,我不想质疑使用可选参数的方法的有效性。这是 VB.NET 允许我做的事情,我觉得我完全有权使用——除了它非常方便!但我最初的问题更多地与可选参数的实现方式(从编译到执行)是否存在差距有关——我在设计代码时应该考虑这些差距。我不知道可选参数方法相对于重载方法的历史意义。我现在了解到,并不是可选参数方法存在差距或缺陷;相反,它是为一组不同的和较旧的问题设计的解决方案,随着公共语言运行时的出现而被简单地覆盖。我正在使用VS2013。当然,使用可选参数方法编译的一切都很好,并且似乎运行良好,但我想确认我没有通过添加可选参数来破坏其他东西——尤其是因为有人查看了我的代码并建议我应该重载该函数.我想证明为什么我不应该保留我的可选参数方法。詹姆斯索普现在为我回答了这个问题,我想。但是正如 Tim Schmelter 所问的那样,与重载方法相比,以这种方式(可选参数)这样做有好处吗?现在对我来说,重载方法似乎是最好也是唯一的方法,那是因为我使用了一组更新的技术,而可选参数方法——这是为微软的旧组件对象模型或 COM 实现的——根本不是。 t 旨在解决(参见本书第 83 页,"Microsoft Visual C# 2013 Step By Step" by John Sharp)。特别是现在,如果有外部模块期望找到旧的函数签名(即,在我添加新的可选参数之前存在的函数参数布局),除非我也重新编译它们,否则它们会中断!这对我来说是个障碍。但是重载可以更好地处理这个软件开发问题,而无需重新编译,现在只有更新的 Common Languange Runtime 或 CLR 才支持这一点。我想 VB.NET 中的可选参数支持现在更像是从旧 COM 时代开始的历史保留——而不是满足我特定要求的最佳解决方案。我还刚刚了解到,“公共语言规范定义了所有语言都应支持的 CLR 子集,明确禁止依赖可选参数。这意味着它们不适合在基类库中使用,并且可能永远不会在作为 .NET Framework 的一部分提供的任何其他库中看到。” (来自在线文章,"Optional Parameters Are Gaining Ground in .NET", by Jonathan Allen)。尽管对于我们这些使用 Microsoft 技术的普通开发人员来说,这些规则更为宽松,但我认为他们内部决定不依赖可选参数的决定还是有话要说的。我只是想发布并与您分享,以防您也像我一样来到这里想知道!

【问题讨论】:

  • 如果新的可选参数只增加了功能,它不应该,如果你改变现有的功能而不考虑参数,那么你可能会遇到问题
  • 如果它“爆炸”了,那是一件好事,而不是风险,你会知道你没有逃脱它。您无法获得保修,只需确保重新编译所有内容即可。
  • 对。而且我并没有改变代码的功能,而是添加了一个新的可选功能,它不会改变以前在函数内部完成的任何事情。我唯一担心的是,是否有可能从其他地方调用该函数的其他代码可能会出现问题,因为意识到有各种来源取决于该代码的调用方式。
  • “如果我坚持使用可选参数会有什么风险” 问题是:“使用可选参数而不是重载有什么好处” ?
  • 我不想质疑使用重载方法的有效性。这是 VB.NET 允许我做的事情。我的问题更多地与从编译到执行的当前实现方式是否存在差距有关。我正在使用VS2013。目前一切编译良好,似乎运行良好,但我想确定。

标签: com overloading clr signature optional-parameters


【解决方案1】:

在单个项目中?不,应该没问题。但是,在您所说的 cmets 中:

假设有其他项目调用它(有可能)。如果我不重建它们会破坏它们吗?

可选参数实际上是在编译时加入的,所以如果你有你原来的方法签名:

Public Function GetContent(ByVal URL As String, ByVal ID As String)

有人这么称呼它:

GetContent(someUrl, someId)

它将按原样编译到它们的程序集中。使用你的新可选参数,任何像上面那样调用它而不传入参数的东西实际上都会被编译为:

GetContent(someUrl, someId, "")

请注意可选参数的默认值是如何自动引入的。如果您要重建所有内容,一切都很好。但是,在那些引用这个未重建的项目中,它们将具有原始的两参数调用。您的 GetContent 方法现在在运行时需要 3 个参数 - 您将收到运行时错误,因为它无法找到仍需要 2 个参数的函数的重载。

【讨论】:

  • 这太糟糕了。因此,CLR 或 .NET 框架中的任何内容都不会发现此问题并在不引发错误的情况下动态解决它?
  • @ShieldOfSalvation 我什么都不知道,没有
  • 如果是这样,那么将可选参数引入现有代码有一个非常大的警告。我希望它必须记录在 Microsoft 文档的某个地方。还没找到。我只发现“自 .NET 1.0 以来可能已经在 Visual Basic 中定义了可选参数”,每个 Microsoft (connect.microsoft.com/VisualStudio/feedback/details/614070/…)。
【解决方案2】:

以下是您如何在不破坏代码的情况下做到这一点...

Public Function GetContent(ByVal URL As String, ByVal ID As String, ByRef PageTitle As String = "") As String
    ' the rest of your function here
End Function

Public Function GetContent(ByVal URL As String, ByVal ID As String) As String
    Return GetContent(URL, ID, "")
End Function

这样你就有了一个函数版本,其中有 2 个参数用于现有代码,一个有 3 个参数。

如果你想鼓励程序员切换到3参数版本,那么你可以这样标记2参数版本:

<Obsolete("Use the version that takes pageTitle as a 3rd parameter">
Public Function GetContent(ByVal URL As String, ByVal ID As String) As String
    Return GetContent(URL, ID, "")
End Function

如果您尝试调用 2 参数版本,这会给您一个编译器警告。

【讨论】:

  • 这是我的编码问题的一个很好的解决方案,但正如我在原始问题中所说,我知道有一个函数重载替代方案,但在我的 StackOverflow 帖子中,我想弄清楚是否可选参数路由本质上是有缺陷或不足的——目前看来确实如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
相关资源
最近更新 更多