通过向 VB.NET 函数添加可选参数来破坏现有代码的机会?

Chance of breaking existing code by adding optional parameter to VB.NET function?

如果我向到处使用的函数添加新的可选参数,大型项目中的现有代码是否有可能崩溃?我知道我可以改为重载该函数并将风险降至最低,但实际上.. 如果我坚持使用可选参数会有什么风险?

这是一个例子:

    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). Particularly now, if there are external modules expecting to find the old function signature (i.e., the function parameter layout that existed before I added the new optional parameter), they'll break unless I recompile them too! That's a hindrance for me. But overloading handles this software development problem much better without need for recompilation, something only now supported by the newer Common Languange Runtime, or CLR. I suppose the optional parameter support in VB.NET is more of a historical holdover now from the old COM days--and not the very best solution for my specific requirements. I've also just learned that, "The Common Language Specification, which defines the subset of the CLR that all languages should support, explicitly disallows a reliance on optional parameters. This means they are not a candidate for use in the Base Class Library and will probably never been seen in any of the other libraries shipped as part of the .NET Framework." (from the online article, "Optional Parameters Are Gaining Ground in .NET", by Jonathan Allen)。尽管规则对于我们这些使用 Microsoft 技术的普通开发人员来说更为宽松,但我认为他们的内部决定不依赖可选参数还是有话要说的。我只是想 post 并与你分享,以防你也像我一样来到这里想知道!

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

Let's say there were other projects calling it (there is a possibility). Would it break those if I didn't rebuild them?

可选参数实际上是在编译时内置的,所以如果您有原始方法签名:

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

有人这样称呼它:

GetContent(someUrl, someId)

它将按原样编译到他们的程序集中。使用新的可选参数,如上调用它而不传递参数的任何内容实际上将被编译为:

GetContent(someUrl, someId, "")

请注意可选参数的默认值是如何自动引入的。如果您正在重建一切,那一切都很好。但是,在那些引用这个 未重建 的项目中,它们将具有原始的双参数调用。您的 GetContent 方法现在在运行时需要 3 个参数 - 您将收到运行时错误,因为它找不到仍然需要 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 参数版本,这会给您一个编译器警告。