web-dev-qa-db-ja.com

なぜparamsキーワードを使うのですか?

これは基本的な質問ですが、答えが見つかりませんでした。

なぜそれを使うの?もしあなたがそれを使っている関数やメソッドを書いたとしても、それを取り除いてもコードは完全に動作するでしょう。例えば:

paramsを使って:

static public int addTwoEach(params int[] args)
{
    int sum = 0;
    foreach (var item in args)
        sum += item + 2;
    return sum;
}

パラメータなし:

static public int addTwoEach(int[] args)
{
    int sum = 0;
    foreach (var item in args)
       sum += item + 2;
    return sum;
}
312
MasterMastic

paramsを使うと、このように自分のメソッドを呼び出すことができます。

addTwoEach(1, 2, 3, 4, 5);

paramsがなければ、できません。

さらに、配列としてパラメータを使用してメソッドを呼び出すことができます。どちらの場合もです。

addTwoEach(new int[] { 1, 2, 3, 4, 5 });

つまり、paramsを使用すると、メソッドを呼び出すときにショートカットを使用できます。

無関係で、あなたは劇的にあなたの方法を短縮することができます:

public static int addTwoEach(params int[] args)
{
    return args.Sum() + 2 * args.Length;
}
457
Konrad Rudolph

paramsを使用すると、引数なしで関数を呼び出すことができます。 paramsがなければ:

static public int addTwoEach(int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // throws an error

paramsと比較してください:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // returns 0

一般に、引数の数が0から無限大まで変化する場合はparamsを使用でき、引数の数が1から無限大まで変化する場合は配列を使用できます。

87
Vasya

それはあなたがあなたが好きなだけあなたの呼び出しに基本型パラメータを追加することを可能にします。

addTwoEach(10, 2, 4, 6)

一方、2番目の形式では、配列をパラメータとして使用しなければなりません。

addTwoEach(new int[] {10,2,4,6})
20
okrumnow

paramsキーワードの危険性の1つは、afterメソッドの呼び出しがコーディングされている場合、

  1. 誰かが誤って/意図的に1つ以上を削除します必須メソッドシグネチャからパラメータ、および
  2. 1つ以上必須署名変更前のparamsパラメーターの直前のパラメーターは、paramsパラメーターと型互換性があり、

これらの呼び出しは、以前にrequiredがオプションのparamsパラメーターとして扱われることを目的とした1つ以上の式でコンパイルを続けます。最悪の場合、paramsパラメーターのタイプはobject[]でした。

これは注目に値します。開発者は、すべてのrequired Parametersでメソッドからパラメーターが削除されるはるかに一般的なシナリオで手首を叩くコンパイラーに慣れているためです(予想されるパラメーターの数が変わるため)。

私にとっては、ショートカットする価値はありません。 (Type)[]なしparamsは、オーバーライドを必要とせずに、0から無限のパラメーター数で機能します。最悪の場合は、, new (Type) [] {}を適用しないCallsに追加する必要があります。

ところで、私見、最も安全な(そして最も読みやすいプラクティス)は次のとおりです。

  1. 名前付きパラメーターを介して渡します(C#〜2でevenを実行できるようになりましたdecades VB; Pで実行可能になった後)(理由:

    1.1。それはonlyであるguaranteesパラメータの順序、Compatible-Type、および/またはコールがコード化された後のカウント変更後にパラメータに渡される意図しない値の防止、

    1.2。 it reducesパラメータの意味が変更された後の可能性。新しい意味を反映する新しい識別子名は、渡される値のすぐ隣にあるため、

    1.3。コンマをカウントし、呼び出しから署名へ前後にジャンプして、どの式がどのパラメーターに渡されているかを確認する必要がなくなります。

    1.3.1。ちなみに、この理由だけでもplentyでなければなりません(頻繁にエラーが発生しやすいDRY原則の違反を避けるためにread言及しないコードmodify it)、ただし、この理由はexponentiallyである可能性があります。コンマを含む1つ以上の式が渡される場合はより重要です。つまり、多次元配列参照または多次元配列参照パラメータ関数呼び出し。その場合、使用することさえできませんでした(できたとしても、さらにステップを追加することになりますperパラメーターperメソッド呼び出し)コンマのカウントを自動化するエディターの選択機能。

    1.4。オプションパラメータ(paramsかどうか)を使用する必要がある場合、特定のオプションパラメータが渡される(したがって、デフォルト値ではないか、少なくともデフォルト値ではない可能性が高いコールを検索できます) )、

(注:理由1.2。および1.3は、呼び出しを読み取りおよび/または変更する必要がある場合は言うまでもなく、最初の呼び出しをコーディングする場合でも、エラーの可能性を緩和および低減できます。)

そして

  1. oNE-PARAMETER-PER-LINEで読みやすくします(理由:

    2.1。整頓されており、

    2.2。左右にスクロールする必要がなくなります(また、ほとんどの人は複数行の左部分を読み取れず、右にスクロールして右部分を読み取ることができないため、行ごとにスクロールする必要があります)。

    2.3。渡されたすべてのパラメーターは本質的に割り当てステートメント(値または参照をローカル変数に割り当てる)であるため、割り当てステートメントのために既に進化した「ベストプラクティス」と一致しています。コーディングスタイルのlatest "Best Practice"に従う人が行ごとに複数の割り当てステートメントをコーディングすることを夢見ていないのと同じように、私たちはおそらくそうすべきではありません(かつては "Best Practice" キャッチアップ私の「天才」; P)パラメーターを渡すときにそうします。

注意

  1. 名前がパラメーターを反映する変数を渡すことは、次の場合には役に立ちません:

    1.1。リテラル定数(つまり、「 'Best Practices'」でさえ名前付き定数を使用する必要がなく、メソッド名からその目的を簡単に推測できない単純な0/1、false/true、またはnullを渡しています。 )、

    1.2。メソッドは、呼び出し元よりも大幅に低レベルで汎用的であるため、変数にパラメーターと同じ/類似した名前を付けたり、逆にしたりすることはできません。または、

    1.3。タイプhappenがまだ互換性があるため、以前の呼び出しがまだコンパイルされている可能性のあるシグネチャのパラメーターを並べ替え/置き換えています。

  2. VSのような自動ラップ機能を使用しても、上記の8つの理由のうち1つ(#2.2)だけが排除されます。 VS 2015より前のバージョンでは、自動インデント(!?!本当にMS?!?)が行われなかったため、理由#2.1の重大度が高くなりました。

VSには、名前付きパラメーター(もちろん行ごとに1つ; P)を持つメソッド呼び出しスニペットを生成するオプションと、requires名前付きパラメーター(概念的にはVBのOption Explicitと同様)ところで、これはかつて同様にとんでもないことであると考えられていた要件が、かつてはとんでもないものでしたが、現在は「必須「ベストプラクティス」」です。実際、「back in my day」;)、1991年に私のキャリアのほんの数か月で、Named Parametersの言語を使用する前に(または見たことさえありましたが)、 /「できるから、やるべきだという意味ではない」/誰にも見られずに(インラインコメントを使用して)それをシミュレートするのに十分なほど「ローストの端を切る」という感覚を盲目的にしないでください。名前付きパラメーターを使用する必要がない(「貴重な」ソースコードのキーストロークを保存する他の構文も)これらの構文のほとんどが始まったときのパンチカード時代の遺物です。読みやすさが非常に重要な最新のハードウェアとIDE、およびはるかに複雑なソフトウェアでは、そのような言い訳はありません。はるかに重要ですMUCH。 「コードは、書かれているよりもずっと頻繁に読み取られます」。自動更新されていないコードを複製しない限り、保存されたすべてのキーストロークは、誰か(あなた自身でさえ)が後でそれを読もうとすると指数関数的に高くなる可能性があります。

16
Tom

オーバーロードメソッドを作成する必要はありません。以下に示すように、paramsで単一のメソッドを使用するだけです。

// Call params method with one to four integer constant parameters.
//
int sum0 = addTwoEach();
int sum1 = addTwoEach(1);
int sum2 = addTwoEach(1, 2);
int sum3 = addTwoEach(3, 3, 3);
int sum4 = addTwoEach(2, 2, 2, 2);
9
electricalbah

Paramsキーワード自体を追加すると、そのメソッドを呼び出している間は複数のパラメーターを渡すことができることがわかりますが、これを使用しないと不可能です。具体的には:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

上記のメソッドを呼び出すときは、次のいずれかの方法で呼び出すことができます。

  1. addTwoEach()
  2. addTwoEach(1)
  3. addTwoEach(new int[]{ 1, 2, 3, 4 })

しかし、あなたはparamsキーワードを削除するとき、上で与えられた方法の3つ目の方法だけでうまくいくでしょう。 1番目と2番目の場合はエラーになります。

4
Ashwini

paramsでは、単一の引数でメソッドを呼び出すこともできます。

private static int Foo(params int[] args) {
    int retVal = 0;
    Array.ForEach(args, (i) => retVal += i);
    return retVal;
}

つまり、Foo(1);ではなくFoo(new int[] { 1 });です。配列全体ではなく単一の値を渡す必要があるかもしれないシナリオで速記するのに役立ちます。それはまだメソッド内で同じ方法で処理されますが、この方法を呼び出すためのいくつかのお菓子を与えます。

4
David Anderson

もう1つ重要なことを強調する必要があります。パフォーマンスに優れているため、paramsを使用することをお勧めします。 params引数を使用してメソッドを呼び出し、それに何も渡さない場合:

public void ExampleMethod(params string[] args)
{
// do some stuff
}

コール:

ExampleMethod();

次に、.Net Frameworkの新しいバージョンがこれを行います(.Net Framework 4.6から):

ExampleMethod(Array.Empty<string>());

このArray.Emptyオブジェクトは後でフレームワークで再利用できるため、冗長な割り当てを行う必要はありません。これらの割り当ては、次のようにこのメソッドを呼び出すと発生します。

 ExampleMethod(new string[] {});
0
Beniamin Makal