8

我有这样的方法:

public void Foo(params string[] args) {
  bar(args[0]); 
  bar(args[1]);
}

新要求导致了这样的变化:

public void Foo(string baz, params string[] args) {
  if("do bar".Equals(baz)) {
    bar(args[0]); 
    bar(args[1]);
  }
}

问题是,即使我更改了方法签名,也没有发生编译错误,这当然是正确的,但我希望每次调用未指定Foo参数的方法时都会出现编译错误。baz也就是说,如果Foo更改之前的调用是这样的:

Foo(p1,p2); //where p1 and p2 are strings

它现在需要是这个:

Foo(baz,p1,p2);

如果不以这种方式更改,p1则将分配给baz,并且 params 数组args的长度为 1 并且OutOfBounds将引发异常。

更改签名并确保所有调用代码都相应更新的最佳方法是什么?(真正的场景是在Foo构建服务器上自动构建的许多项目共享的程序集中。因此,编译错误将是检测所有需要修改以适应更改的代码的简单方法。)

编辑: 正如 Daniel Mann 和其他人指出的那样,上面的例子表明我根本不应该使用 params。所以我应该解释一下,在我的真实示例中,args 并不总是需要有两个元素,就 Foo 中的逻辑而言,args 可以包含任意数量的元素。假设这是 Foo:

public void Foo(string baz, params string[] args) {
  if("do bar".Equals(baz)) {
    int x = GetANumberDynamically();
    for(int i = 0; i<x; i++)
      bar(args[i]); 
  }
}
4

2 回答 2

3

这是解决方案。不要更改以前的方法签名,只需添加Obsolete指定了两个参数的属性。

[Obsolete("Use Foo(string, params string[]) version instead of this", true)]
public void Foo(params string[] args) {
  bar(args[0]); 
  bar(args[1]);
}

然后创建一个带有新签名的新方法。

public void Foo(string baz, params string[] args) {
  if("do bar".Equals(baz)) {
    bar(args[0]); 
    bar(args[1]);
  }
}

Obsolete属性中的第二个参数确保编译错误。没有它只会导致编译警告。MSDN上提供了有关该属性的更多信息。

编辑:

基于下面评论中的讨论,Daniel Mann 提出了一个有趣的问题。

那不会解决问题。如果你调用 Foo("a", "b") 呢?在这种情况下,它仍然会调用只有两个参数的非过时方法,并导致同样的问题。

args我建议在调用之前检查是否有超过一个参数通过bar

于 2013-12-05T13:24:10.420 回答
2

如果您有必需的参数,最简单的解决方案是不使用params关键字。

显然,您期望args包含至少两个参数。可以肯定地说,这些都是必需的。为什么没有这样的方法签名?

public void Foo(string baz, string requiredArgument1, string requiredArgument2, params string[] optionalArguments)

这消除了歧义:它总是需要至少 3 个参数。

出于某种原因,我什至没有想到的另一个选择是使用命名参数。显然,您的所有代码都必须明确地这样做,但您可以这样做:

Foo(baz: "bar", args: new [] {"a", "b", "c"});

于 2013-12-05T13:52:18.210 回答