【问题标题】:Add optional parameter to function after a "params object[]" parameter在“params object[]”参数之后添加可选参数以函数
【发布时间】:2019-08-16 07:51:30
【问题描述】:

我在一个 API 中有一个函数,许多其他库都在使用它,但我想将它调整为一个新特性,以采用一个添加的可选参数。方法签名是:

protected Task EnvGetJsonAsync<TReceive>(string endpointName, params object[] pathArgs)

并且我想在 pathArgs 之后添加“string key = null”,因为我有 37 个对用于此格式的函数的引用。这样我就不必更改所有 37 个引用(而且大多数引用不需要可选参数),我只想在最后添加一个可选参数。

我尝试将“params object[]”更改为“object[]”,但它导致所有引用出错。所以它看起来像这样

protected Task EnvGetJsonAsync<TReceive>(string endpointName, params object[] pathArgs, string id = null)

然后是这个

protected Task EnvGetJsonAsync<TReceive>(string endpointName, object[] pathArgs, string id = null)

但两者都引起了问题。我想要一种方法来允许函数采用可选参数而不破坏其他 37 个引用。谢谢!

【问题讨论】:

  • 你不能真正做到这一点。 params 参数必须是形式参数列表中的最后一个参数。但是,向方法添加参数,即使是可选参数也是一项重大更改。可以说,最好简单地添加一个具有新名称的新方法,该方法采用新参数,然后跟随一个可选参数列表。
  • 可以不使用可选参数,而是使用方法重载和创建方法:protected Task EnvGetJsonAsync&lt;TReceive&gt;(string endpointName, string id, param object[] pathArgs,)。在内部,这两种方法都可以调用相同的私有方法,并且您不会破坏现有的引用。
  • @AnkitVijay 虽然这是合法的,但我会注意到这可能会导致行为的细微变化,具体取决于 id 参数在方法中的作用。想象一下我有EnvGetJsonAsync&lt;Type&gt;("endpointname", 'path/arg")。 pathArgs 是一个包含一项的数组。当我使用新库重新编译时,重载解析选择了不同的方法,id 为“path/arg”,pathArgs 为空。如果 id 参数在语义上不同,则可能需要一种新方法。
  • 嗨 @mjwills 和 Mike,我的写作速度比我想象的要快。谢谢你纠正我:)

标签: c#


【解决方案1】:

您可以将可选参数移到param 之前。根据MSDN

a 中的 params 关键字后面不允许有其他参数 方法声明,并且只允许一个 params 关键字在 方法声明。

最好为新输入创建新方法,并根据输入从那里调用现有方法。

重载不适用于param。您不会收到任何编译时错误。它将在运行时调用最后一个方法。您可以查看此fiddler 了解更多信息。

【讨论】:

    【解决方案2】:

    只需创建一个新方法,将实现移到那里并使用旧方法调用新方法。这样一来,您的 37 个调用者将永远不会注意到变化:

    protected Task EnvGetJsonAsync<TReceive>(string endpointName, params object[] pathArgs)
    {
      // this is the original method. Here we just call the new one
      return EnvGetJsonoAsync<TReceive>(endpointName, null, pathArgs);
    }
    
    protected Task EnvGetJsonAsync<TReceive>(string endpointName, string id, params object[] pathArgs) 
    {
      .. the code implementation
    }
    

    【讨论】:

    • That way your 37 callers will never notice the change: 除非他们将字符串作为第二个参数传递。 ;)
    • 您说得对,先生!在这种情况下,重载决议将更喜欢第二种方法。谢谢!
    【解决方案3】:

    根据文档,params 之后不能有可选参数:

    方法声明中params关键字后面不允许有附加参数,方法声明中只允许一个params关键字。

    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params

    您可以在params 之前放置可选参数,但是因为您的params 数组类型是object,如果您第一次选择错误的方法,您可能会遇到运行时错误pathArgs 类型是 string

    最好的方法是使用您的可选参数添加一个新方法,使用稍微不同的名称。然后,您的参考方法可以使用适当的方法,无论它们是否具有密钥。然后,您可以使用 null 或 key 的默认值从旧方法调用新方法:

    protected Task EnvGetJsonAsync<TReceive>(string endpointName, params object[] pathArgs)
    {
        return EnvGetJsonWithKeyAsync<TReceive>(endpointName, null, pathArgs);
    }
    
    protected Task EnvGetJsonWithKeyAsync<TReceive>(string endpointName, string key, params object[] pathArgs)
    {
        // your method here
    }
    

    【讨论】:

    • The best way would be to add a new method with your optional parameter 很好的解决方案,对现有呼叫者没有风险。
    猜你喜欢
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    相关资源
    最近更新 更多