web-dev-qa-db-ja.com

必須ではありませんが、オプションのパラメーター名を指定しますか?

次の方法を検討してください。

public List<Guid> ReturnEmployeeIds(bool includeManagement = false)
{

}

そして次の呼び出し:

var ids = ReturnEmployeeIds(true);

システムに不慣れな開発者にとって、trueが何をしたのかを推測するのはかなり難しいでしょう。最初に行うことは、メソッド名にカーソルを合わせるか、定義に移動することです(どちらも少し大きなタスクではありません)。しかし、読みやすくするために、次のように書くのは理にかなっています。

var ids = ReturnEmployeeIds(includeManagement: true);

コンパイラが必要としない場合に、オプションのパラメータを明示的に指定するかどうかを正式に議論する場所はありますか?

次の記事では、特定のコーディング規約について説明しています。 https://msdn.Microsoft.com/en-gb/library/ff926074.aspx

上記の記事に似たものがいいでしょう。

26
JᴀʏMᴇᴇ

C#の世界では、列挙型はここでの最良のオプションの1つになると思います。

それであなたはあなたが何をしているのかを綴ることを強いられ、どんなユーザーも何が起こっているのか見るでしょう。また、将来の拡張に対しても安全です。

public enum WhatToInclude
{
    IncludeAll,
    ExcludeManagement
}

var ids = ReturnEmployeeIds(WhatToInclude.ExcludeManagement);

だから、ここで私の意見では:

列挙型>オプションの列挙型>オプションのブール値

編集:以下のLeopardSkinPillBoxHatとの[Flags] enumについての議論のため、この特定のケースに適している可能性があるため(具体的には包含/除外について話しているため)、代わりにISet<WhatToInclude>をパラメータ。

これは、より「モダンな」コンセプトであり、いくつかの利点があります。これは主に、コレクションのLINQファミリに適合するという事実に由来しますが、[Flags]には最大32のグループがあることも原因です。 ISet<WhatToInclude>を使用する主な欠点は、C#構文でサポートされているセットがどれほどひどいかです。

var ids = ReturnEmployeeIds(
    new HashSet<WhatToInclude>(new []{ 
        WhatToInclude.Cleaners, 
        WhatToInclude.Managers});

セットの生成と、次のような「ショートカットセット」の作成の両方のために、ヘルパー関数によって一部が軽減される場合があります。

var ids = ReturnEmployeeIds(WhatToIncludeHelper.IncludeAll)
28
NiklasJ

書くのは意味がありますか:

 var ids=ReturnEmployeeIds(includeManagement: true);

これが「良いスタイル」であるかどうかは議論の余地がありますが、私見では、コード行が「長すぎない」限り、少なくとも悪いスタイルではなく、便利です。名前付きパラメーターがない場合、説明変数を導入することも一般的なスタイルです。

 bool includeManagement=true;
 var ids=ReturnEmployeeIds(includeManagement);

名前付きパラメーターはバージョン4.0より前の言語の一部ではなかったため、このスタイルはおそらく名前付きパラメーターバリアントよりもC#プログラマーの間で一般的です。読みやすさへの影響はほとんど同じで、追加のコード行が必要です。

したがって、私の推奨:異なる名前の列挙型または2つの関数を使用することが「やり過ぎ」であると思われる場合、または異なる理由で署名を変更したくない、または変更できない場合は、名前付きパラメーターを使用してください。

20
Doc Brown

次のようなコードに遭遇した場合:

public List<Guid> ReturnEmployeeIds(bool includeManagement = false)
{

}

{}の内容が次のようになることをほぼ保証できます。

public List<Guid> ReturnEmployeeIds(bool includeManagement = false)
{
    if (includeManagement)
        return something
    else
        return something else
}

つまり、ブール値は2つのアクションコースから選択するために使用されます。メソッドには2つの責任があります。 これはコードのにおいがほぼ保証されています 。メソッドが1つのことだけを実行するように常に努力する必要があります。責任は1つだけです。したがって、私はあなたの両方の解決策が間違ったアプローチであると主張します。オプションパラメータの使用は、メソッドが複数のことを実行していることを示しています。ブール型パラメーターもこの兆候です。両方を持っていることは間違いなく警報ベルが鳴るように設定する必要があります。したがって、2つの異なる機能セットを2つの別々のメソッドにリファクタリングする必要があります。メソッド名を、それらが何をするのかを明確にするために与えます。例えば:

public List<Guid> GetNonManagementEmployeeIds()
{

}

public List<Guid> GetAllEmployeeIds()
{

}

これにより、コードの可読性が向上し、SOLIDの原則に確実に従うことができます。

[〜#〜] edit [〜#〜]コメントで指摘されているように、これらの2つのメソッドが機能を共有している可能性があるケース、そしてその共有機能はプライベート関数でラップするのが最も良いでしょう。プライベート関数はその機能のいくつかの側面を制御するためにブールパラメータを必要とします。

この場合、コンパイラーはパラメーター名を必要としませんが、パラメーター名を指定する必要がありますか?それに対する単純な答えはなく、その判断はケースバイケースで必要となることをお勧めします。

  • 名前を指定するための議論は、他の開発者(6か月後の自分も含む)がコードの主要な対象者であるべきだということです。コンパイラは間違いなく二次的読者です。したがって、他の人が読みやすいようにコードを常に記述してください。コンパイラが必要とするものを提供するだけではありません。このルールを毎日使用する方法の例は、コードに変数_1、_2などを入力せず、意味のある名前を使用することです(コンパイラーには何も意味しません)。
  • 反対の議論は、プライベートメソッドは実装の詳細であるということです。以下のようなメソッドを見ている人はだれでも、コードの内部にいるため、コードをたどってブールパラメータの目的を理解することが合理的に期待できます。
public List<Guid> GetNonManagementEmployeeIds()
{
    return ReturnEmployeeIds(true);
}

ソースファイルとその方法は、小さくて簡単に理解できますか?はいの場合、名前付きパラメーターはおそらくノイズになります。いいえの場合、それは非常に役立つでしょう。状況に応じてルールを適用してください。

17
David Arno

システムに不慣れな開発者にとって、本当のことを推測するのはかなり難しいでしょう。最初に行うことは、メソッド名にカーソルを合わせるか、定義に移動することです(どちらも少し大きなタスクではありません)。

そうですね。自己文書化コードは美しいものです。他の回答が指摘しているように、列挙型や異なるメソッド名などを使用して、ReturnEmployeeIdsへの呼び出しのあいまいさを解消する方法があります。ただし、場合によっては本当に回避できない場合がありますが、離れてどこでもそれらを使用したい(Visual Basicの冗長性が好きでない限り)。

たとえば、1つのコールを明確にするのに役立つ場合がありますが、必ずしも別のコールではありません。

名前付き引数はここで役に立ちます:

var ids = ReturnEmployeeIds(includeManagement: true);

それほど明確さを追加しないでください(これが列挙型を解析していると思います):

Enum.Parse(typeof(StringComparison), "Ordinal", ignoreCase: true);

それは実際に明快さを減らすかもしれません(人がリストの容量が何であるか理解していない場合):

var employeeIds = new List<int>(capacity: 24);

または、適切な変数名を使用しているため、問題にならない場合:

bool includeManagement = true;
var ids = ReturnEmployeeIds(includeManagement);

コンパイラが必要としない場合に、オプションのパラメータを明示的に指定するかどうかを正式に議論する場所はありますか?

AFAIKではありません。ただし、両方の部分を取り上げましょう。名前付きパラメーターを明示的に使用する必要があるのは、コンパイラーがそうする必要があるためです(通常、ステートメントのあいまいさを取り除くためです)。それ以外は、いつでも好きなときに使用できます。 MSのこの記事には、いつ使用したいかに関するいくつかの提案がありますが、特に決定的なものではありません https://msdn.Microsoft.com/en-us/library/dd264739.aspx

個人的には、カスタム属性を作成するときや、パラメーターが変更または並べ替えられる可能性がある新しいメソッドをスタブアウトするときに最も頻繁に使用します(名前付き属性は任意の順序でリストできます)。さらに、静的な値をインラインで提供する場合にのみ使用します。そうでない場合は、変数を渡す場合は、適切な変数名を使用しようとします。

TL; DR

最終的には個人の好みに帰着します。もちろん、名前付きパラメーターを使用する必要があるいくつかのユースケースがありますが、その後、判断コールを行う必要があります。 IMO-コードの文書化、あいまいさの軽減、またはメソッドシグネチャの保護に役立つと思われる任意の場所で使用します。

1
user211925

パラメータがメソッドの(完全修飾)名から明らかであり、その存在がメソッドの想定どおりである場合は、not名前付きパラメータ構文を使用する必要があります。たとえば、ReturnEmployeeName(57)では、_57_が従業員のIDであることは明らかです。そのため、名前付きパラメーター構文で注釈を付けることは冗長です。

あなたが言ったように、ReturnEmployeeIds(true)では、関数の宣言/ドキュメントを調べない限り、trueの意味を理解することは不可能です。つまり、should名前付きパラメーター構文を使用します。

ここで、この3番目のケースを考えます。

_void PrintEmployeeNames(bool includeManagement) {
    foreach (id; ReturnEmployeeIds(includeManagement)) {
        Console.WriteLine(ReturnEmployeeName(id));
    }
}
_

名前付きパラメーターの構文はここでは使用されませんが、ReturnEmployeeIdsに変数を渡していて、その変数には名前があり、その名前は、渡したパラメーターと同じことを意味します(this常にそうであるとは限りませんが、常にそうではありません!)-コードから意味を理解するために、名前付きパラメーター構文は必要ありません。

したがって、ルールは単純です。メソッド呼び出しからパラメーターの意味が簡単に理解できる場合は、名前付きパラメーターを使用しないでください。できない場合-それはコードの可読性の欠陥であり、おそらくそれらを修正したいでしょう(もちろん、価格は高くありませんが、通常はコードを読みやすくしたいです)。修正は名前付きパラメーターである必要はありません-結果がパラメーターの機能を簡単に理解できる限り、最初に変数に値を入れるか、他の回答で提案された方法を使用することもできます。

0
Idan Arye

はい、いいスタイルだと思います。

これは、ブール定数と整数定数に対して最も意味があります。

変数を渡す場合は、変数名によって意味が明確になるはずです。そうでない場合は、変数により良い名前を付ける必要があります。

文字列を渡す場合、その意味はしばしば明確です。 GetFooData( "Oregon")への呼び出しが表示されるように、パラメーターが状態名であると読者はかなり推測できると思います。

もちろん、すべての文字列が明白なわけではありません。 GetFooData( "M")が表示された場合、関数がわからなければ、 "M"の意味がわかりません。 M = "管理レベルの従業員"のようなコードの場合、おそらくリテラルではなく列挙型が必要であり、列挙名は明確である必要があります。

そして、文字列は誤解を招く可能性があると思います。上の例の「オレゴン」は、州ではなく、製品やクライアントなどを指しているのかもしれません。

しかし、GetFooData(true)またはGetFooData(42)...これは何を意味する可能性があります。名前付きパラメーターは、それを自己文書化する素晴らしい方法です。私は多くの場合、まさにその目的のためにそれらを使用しました。

0
Jay

最初にこのタイプの構文を使用する理由として、super clear理由はありません。

一般に、遠くから任意に見えるブール引数を持たないようにしてください。 includeManagementは(ほとんどの場合)結果に大きな影響を与えます。しかし、議論はそれが「小さな重み」を運ぶように見えます。

列挙型の使用については議論されてきました。それは、引数が「重みを運ぶ」ように見えるだけでなく、メソッドにスケーラビリティを提供することにもなります。ただし、ReturnEmployeeIds-メソッドはWhatToInclude- enumと一緒にスケーリングする必要があるため、これはすべての場合に最適な解決策ではない可能性があります( NiklasJ の回答を参照) 。これは後で頭痛の種になるかもしれません。

これを考慮してください:WhatToInclude- enumをスケーリングするが、ReturnEmployeeIds- methodをスケーリングしない場合。次に、ArgumentOutOfRangeException(最良の場合)をスローするか、まったく望ましくないもの(nullまたは空の_List<Guid>_)を返します。特にReturnEmployeeIdsがソースコードがすぐに利用できないクラスライブラリにある場合は、プログラマーを混乱させる場合があります。

_WhatToInclude.Trainees_が機能する場合、_WhatToInclude.All_が機能すると想定して、研修生がすべての「サブセット」であることがわかります。

これは(もちろん)、方法に依存しますReturnEmployeeIdsが実装されています。


ブール引数を渡すことができる場合は、代わりに、引数を2つのメソッド(必要な場合はそれ以上)に分割しようとします。 ReturnAllEmployeeIdsReturnManagementIdsおよびReturnRegularEmployeeIdsを抽出できます。これはすべてのベースをカバーし、それを実装する誰にとっても完全に自明です。これには、上記の「スケーリング」の問題もありません。

ブール値の引数を持つものに対しては2つの結果しかないためです。 2つのメソッドを実装しても、追加の作業はほとんど必要ありません。

コードが少ないほど、良いことはめったにありません。


これについては、引数を明示的に宣言することで可読性が向上する場合がありますがあります。たとえば考えてみてください。 GetLatestNews(max: 10)GetLatestNews(10)stillかなり自明であり、maxの明示的な宣言はany混乱。

そして、もしあなたが絶対に必要な場合ブール引数を持っている場合、その使用法はtrueまたはfalseを読み取るだけでは推測できません。それから私はそれを言うでしょう:

_var ids = ReturnEmployeeIds(includeManagement: true);
_

..は絶対に優れており、より読みやすくなっています。

_var ids = ReturnEmployeeIds(true);
_

2番目の例では、trueは絶対的に何でもを意味する場合があります。しかし、私はこの議論を避けようとします。

0
die maus