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 をまったく使用しないことを示唆しています。したがって、実世界の例では、Foo のロジックに関する限り、args に 2 つの要素が必要であるとは限らないことを説明する必要があります。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]);
  }
}

属性の 2 番目の引数はObsolete、コンパイル エラーを保証します。それがないと、コンパイル警告が発生するだけです。属性の詳細については、MSDNを参照してください。

編集:

以下のコメントでの議論に基づいて、Daniel Mann は興味深い問題を思いつきました。

それでは問題は解決しません。Foo("a", "b") を呼び出すとどうなりますか? その場合、廃止されていないメソッドを 2 つの引数だけで呼び出し、同じ問題を引き起こします。

argsを呼び出す前に、複数の引数が渡されているかどうかを確認することをお勧めしbarます。

于 2013-12-05T13:24:10.420 に答える
2

最も簡単な解決策は、必要なパラメーターparamsがある場合はキーワードを使用しないことです。

args明らかに、少なくとも 2 つのパラメーターが含まれていることを期待しています。それらが必要であると言っても過言ではありません。このようなメソッド署名を持たないのはなぜですか?

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 に答える