web-dev-qa-db-ja.com

C#-フィールドの接頭辞が推奨されないのはなぜですか?

昔はハンガリー語で表記していました。これはpasséと見なされ、ほとんどの場合、もう使用しませんが、m_プレフィックスは、メンバーフィールドを示します。

私にとって、他の誰かのコードを読んでいて、これを見ると:

count = 3;

countはその関数にローカルな変数であると想定し、関数の他の場所で使用されることを実行しています。私がこれを見た場合:

m_count = 3;

オブジェクトの状態を更新していることにすぐに気付きました。

マイクロソフトスタイルのガイドラインによると、これは物事を行うには間違った方法です。非公開フィールドには、関数内で定義された一時変数とまったく同じ名前を付けることになっています。番号 m_、単純なアンダースコアすらありません。

はい、独自のコーディングスタイルを定義できますが、私はさまざまな静的コード分析ツールに取り組み、私たちのやり方が大丈夫であることを彼らに納得させる必要があります。

マイクロソフトスタイルに変更できてうれしいですが、なぜなのかを知りたいのですが。

変数が関数のローカルなのかメンバーなのかを判別できないのはなぜ悪いと思われるのですか?

追伸これは c#のフィールドとメソッドの前にある「this」キーワードに関して現在考えられているベストプラクティスは何ですか? ですが、m_ないthis.

P.P.S.また参照 Microsoftがパラメーター、ローカル変数、プライベートフィールドに同じ名前の命名規則を使用したのはなぜですか?

21
Betty Crokker

彼らがWindowsのAPIに取り組んでいたとき、Microsoftはハンガリー語表記、「m _」、「i」、「sz」などを使用することを推奨しました。IDEは、この情報を表示するほど堅牢ではありませんでした。

一方、C#は最初から非常に堅牢なIDEを持っています。

したがって、パブリック静的フィールドまたは保護フィールドについて MicrosoftのC#の命名ガイドライン を推奨しました。

✓ DO use PascalCasing in field names.
✓ DO name fields using a noun, noun phrase, or adjective.
X DO NOT use a prefix for field names.

マウスでポイントするか、CTRL + K + Wを押してメンバーに関するすべての情報を取得できるようになったので、Microsoftは接頭辞が不適切な形式であると判断しました。それらはすでに解決された問題に対する手動の解決策です。

プライベートフィールドはガイドラインから明確に除外されていますが、Microsoftは、プライベートフィールドが内部的に進む場合でもそうであるという結論に達しているようです。

ツールを使用してください。手動で行わないでください。

20
Kevin Fee

C#にはグローバル変数がないため、ローカル変数とクラスフィールドのみが残ります。

そして、非常に多くのローカル変数があり、識別子が1であるかどうかを見失うと、複雑さを最も厳しく管理するためのガイドラインの1つに確実に違反したことになります。

パラメータオブジェクトを抽出し、関数をより単純なものに分割してみてください。細部や複雑さに溺れ、メンテナンス性を考慮しない場合を除き、コードをリファクタリングする必要があります。

関数スコープが小さすぎてグローバルスコープが存在しないため、 "this-is-a-member"装飾の目的はもはや成り立たないことを確立したので、これらのマーカーには1つの欠点があります。引数/ローカル変数をメンバーに移動する、またはその逆。

17
Deduplicator

開発者がusing名前空間ディレクティブを名前空間の前に付けるのを避けるのはなぜですか?

System.DateTime()DateTime()よりも明確です。それは私が扱っていることを正確に教えてくれます。私たちが怠惰なタイピストだからというだけのことですか?

いいえ。私たちは怠惰なタイピストですが、それが理由ではありません。

詳細を無視して抽象化に集中できるコーディングスタイルを好みます。名前に構造の詳細を伝えることを強制するのは邪魔です。複雑なアルゴリズムに取り組んでいるとき、自分が扱っていることについて細かいところまで思い出させるような名前は欲しくない。 TimerDateTimeを混同しないように、名前だけが必要です。他の場所で互換性があるかどうか心配です。

これは、Jonという名前のチームに2人の男を配置したくないのと同じ理由です。彼らに姓があるという事実は、彼らに接頭辞や接尾辞を付ける理由にはなりません。私はあなたをスキートと呼ぶつもりです。それ以上のものは平らな痛みです。

12
candied_orange

少し広げましょう。

3つの一般的な接頭辞スタイルがあり、それらはすべてc#コードで時々見られます。

  • m_
  • _
  • この。

このようなプレフィックスは、クラスのプライベート実装で一般的に使用されます。マイクロソフトの推奨事項は、主にクラスの公開された部分に関するものです。

m_よりも_を使用する利点は、c#および プレフィックスとして_を使用できない言語 。*を使用すると、コードベース全体でプレフィックスが同じになる可能性があることです。短いので、誤ってプレフィックスを忘れることはありません。

m_よりもthis.を使用する場合の利点は、_よりも短く、接頭辞で始まるすべてのものがツールでアルファベット順にソートされることです。 m_よりも_を使用する場合の利点は、this.より短く、誤って接頭辞を忘れないことです。

this.およびm_に対する_の利点は、_またはm_が受け入れられていない一般的な規則ではないコードベースで使用できることです。これは、_またはm_の規則について誰も知る必要がないことも意味します。欠点として、コンパイラーはこのプレフィックスを考慮しないため、this.プレフィックスが欠落することがあり、インジケーターほど信頼性が低くなります。


* C++/CLIから_を使用するC#クラスへのアクセスを開始すると(実際には_を使用すべきではありません)、共通のプレフィックスの合意が必要以上に複雑であることがわかります。接頭辞を付けないことを決定すると、そのノイズが取り除かれます。これをDeduplicatorの回答と組み合わせます。これを「接頭辞の利点はほとんど無視できる」と言い換えると、次のようになります:それらを使用しないことは有効な選択です。」


これに関連する stackoverflowに関する古い質問 があります。

7
Peter

MSスタイルガイドでは、パブリックおよび保護されたメソッドと変数についてのみ説明していることに注意してください。つまり、他の開発者がライブラリを使用しているかどうかを確認します。

Microsoftライブラリは、それらを使用する開発者に標準のルックアンドフィールが与えられるという考えです。

プライベート変数またはローカル変数で好きなスタイルを自由に使用できます。

変数の接頭辞は、一般的にいくつかの理由で推奨されないと述べた

  • それらは間違っている可能性があり、したがって誤解を招く可能性があります
  • 変数タイプで接頭辞を付ける場合は、作成したクラスの処理方法が明確ではありません。
  • いくつかの規則があり、それらは常に同意するわけではありません。他の開発者が役に立たないと感じるかもしれないもの
  • メンバー変数の場合は、これを使用できます。スコープを示すキーワードとコンパイラはそれを強制します。
6
Ewan

「メンバー」プレフィックスは、実装の詳細の一種です。問題領域からテクニカルソリューション領域へと注意をそらし、考えられるリファクタリングを考えるときに心を偏らせます。 –私

さらに説明できますか?プレフィックスを使用しない理由を私が見た唯一の理由はあなたのものです(それが理解できない...)つまり、人々が言っ​​ている他のことは、私がプレフィックスを使用する必要がない理由です、これは私がなぜすべきでないのと同じではありません)– Betty Crokker

私のポイントは、@ CandiedOrangeと@Ewanの回答を拡張することです。

プレフィックスはリファクタリングを難しくします

コードが進化するにつれて、変数とメソッドはスコープを変更する可能性があります。例えば。プライベートメソッドを作成し、後で他の(新しい)クラスでも使用できるようにする必要がある場合があります。メソッドパラメータとローカル変数についても同様です。

税計算機を作成するとします。 リース可視性スコープの原則に従って、変数として税率基本値の両方をパラメーターとして取るメソッドで開始します。
(例はJava風に見えるかもしれません...)

class TaxCalculator{
   double Calculate(double p_TaxRateInpercent, double p_BaseValue){
     return (100+p_TaxRateInpercent)/100 * p_BaseValue;
   }
} 

次に、逆の操作を実装する必要があり、TDDによると、最小限の労力でそれを実行します。

class TaxCalculator{
   double Calculate(double p_TaxRateInpercent, double p_BaseValue){
     return (100+p_TaxRateInpercent)/100 * p_BaseValue;
   }
   double CalculateBase(double p_TaxRateInpercent, double p_TaxedValue){
     return p_TaxedValue/((100+p_TaxRateInpercent)/100);
   }
} 

次にTDDは、コードをよりリファクタリングして、両方のメソッドのパラメータリストを減らすことを要求します。
(はい、あなたは最初に2倍の計算を抽出しますが、私のポイントを取得させてください...)
明白な解決策は、コンストラクターパラメーターとして渡すことにより、税率をメンバー変数に変更することです。

class TaxCalculator{
   double m_TaxRateInpercent;
   TaxCalculator(double p_TaxRateInpercent){
     m_TaxRateInpercent = p_TaxRateInpercent;
   }
   double Calculate(double p_BaseValue){
     return (100+m_TaxRateInpercent)/100 * p_BaseValue;
   }
   double CalculateBase(double p_TaxedValue){
     return p_TaxedValue/((100+m_TaxRateInpercent)/100);
   }
} 

ご覧のとおり、既存のメソッドのall行を変更する必要がありました(正確には、p_TaxRateInpercentを使用したすべての行)。

問題は、クラス全体で名前の変更を行うIDEからのサポートなしがあることです。唯一の助けsearch/replaceコンストラクタまたは文字列p_TaxRateInpercentを誤って含む部分も変更します。
あなたはIDEが提供するかもしれませんに変更...未定義の変数名のリファクタリングがこれはメソッドのスコープに制限されるかもしれません

接頭辞がなければ、メソッドシグネチャのみが変更されます。名前を変更する必要はまったくありませんでした。


変更時にSCM履歴を整理する

また、[〜#〜] scm [〜#〜]は、ロジックは変更されなかったものの、ロジックの変更としてプレフィックスの変更を記録します。 SCMの歴史は、重要なものを隠し、他の(実際のロジック)変更との競合のリスクを高めるこの技術変更で乱雑になっています。

5
Timothy Truckle

私にとって、他の誰かのコードを読んでいて、これを見ると:

count = 3;

「カウント」はその関数にローカルな変数であると仮定し、関数の他の場所で使用されることをしています

そして、あなたは完全に正しいでしょうifあなたはC#のスタイル規約を尊重するソースコードを読んでいます。このようなコードでは:

this.count = 3;

フィールドに値を割り当てます。

count = 3;

ローカル変数に値を割り当てます。

したがって、C#のスタイル規則は明確で明確です。彼らはあなたにどんな接頭辞も使わないように強制しますあなたがそれを必要としないので単に。

代わりに作者が個人的な慣習を使用することを決定したソースコードについては、なぜthemに彼らがそうすることを選択したのかを個人的に尋ねる必要があります。アンダースコアなどの接頭辞を使用せず、this.も使用しない場合、コードの読み取りが困難になるだけでなく、追加の規則が必要になる場合もあります。

public class Hello
{
    private string greetings;

    public Hello(string greetings)
    {
        greetings = greetings; // Wait, what is that?!
    }
}

C#にはthisキーワードはありませんか? this.countなど、これを使用してメンバーを参照できませんか?

はい、しかし(1)それはよりタイピングします、そして(2)それは忘れがちです。フィールドの名前がm_countの場合、これを入力する必要はありません。m_count

しかし、ここでは、あなたは間違っています。

メモ帳でコードを書くと、よりタイピングが多くなります。 IDEオートコンプリートを使用するか、IntelliSenseを使用した場合、this.countm_countの比較はそれほど明白ではありません。 Shift+- アンダースコアを入力する必要があります。

「忘れやすい」については、これもメモ帳のユーザーにのみ関係します。 StyleCopとResharperは、必要なときにthis.を置くことを忘れないだけでなく、数時間のプログラミングの後、必要なときにthis.を置くことが習慣になります。

4

すべてのメンバー変数に_接頭辞を使用しています。 'this'接頭辞は嫌いです。なぜなら、それが物事を行うための正しい方法であると主張する人もいます。コードベースに多くのノイズ/混乱を追加するからです。単一の下線も、Microsoftのサンプルでは一般的な方法です。

だからあなたの例では私は持っているでしょう:

int _count = 10;
1
Eternal21