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

Shi*_*ion -1 com clr overloading signature optional-parameters

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

这是一个例子:

    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
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*rpe 5

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

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

可选参数实际上是在编译时引入的,因此如果您有原始方法签名:

Public Function GetContent(ByVal URL As String, ByVal ID As String)
Run Code Online (Sandbox Code Playgroud)

有人这样称呼它:

GetContent(someUrl, someId)
Run Code Online (Sandbox Code Playgroud)

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

GetContent(someUrl, someId, "")
Run Code Online (Sandbox Code Playgroud)

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