C#-フィールドのプレフィックスが推奨されないのはなぜですか?


19

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

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

count = 3;

私はそれcountがその関数のローカル変数であると仮定し、関数の他の場所で使用される何かをしています。私がこれを見たら:

m_count = 3;

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

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

はい、独自のコーディングスタイルを定義することはできますが、その後、さまざまな静的コード分析ツールに取り組み、物事のやり方が問題ないことを説得する必要があります。

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

変数が関数ローカルであるかメンバーであるかを判断できるのはなぜ悪いと考えられるのですか?

PSこれは、C#のフィールドとメソッドの前にある「this」キーワードに関して現在考えられているベストプラクティスと非常に似ていますか?、しかし私は聞いてm_いないthis.

PPSまた、Microsoftがパラメーター、ローカル変数、およびプライベートフィールドに同じ名前の命名規則を付けた理由を参照してください


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

3
m_プレフィックスは、フィールドとメソッド間の名前の衝突を避けるC ++主義です。C#では、メソッド名は大文字で、フィールドは小文字で始まる必要があるため、これは問題になりません。
アモン

4
2017年にコードを印刷する場合、何か間違ったことをしていることになります。他の2つのシナリオでcountは、メソッドで宣言されていないため、どこからともなく現れなかったことはかなり明白です。率直に言って、「IDEからの」引数は本当に弱いです。特に、IDEで機能するコードレビューツールもあるためです。
アンディ


回答:


19

Windows用のAPIで作業しているとき、Microsoftは「i」、「sz」などと同様に「m_」を使用したハンガリー語表記の使用を推奨していました。この情報を表示するのに十分です。

一方、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は内部的に進んでいるプライベートフィールドにも当てはまるという結論に達しているようです。これは、Resharperを.NET 4.5または。

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


2
Andyと同じ答えです...はい、しかし... IDEの外でコードを見ている多くの状況があります。例-(1)マージツール。(2)コードレビューツール。(3)(gasp)プリントアウト。
ベティクロッカー

アンディは文字通り私が行ったのと同じ瞬間を投稿しました。「回答を追加」をクリックすると、「1つの新しいコメント」がポップアップ表示されました。これらのツールに関しては、そのうちの2つはすでにIDEにあります。印刷...なぜあなたはそれをしているのですか?
ケビンフィー

1
私の最初の質問は未回答のままです...はい、Microsoftはm_を使用しないと言いました、そして、ツール製造業者はそれに続きました、それはm_を使用する技術的な理由ではなく、それはしばしば「権威への訴え」と呼ばれるものです。m_を使用しないと見た唯一の技術的な理由は、ティモシー
トラッケル

8
@BettyCrokker m_はまったく値を追加しないため。IDEはメンバーかどうかを通知するため、m_は冗長です。なんでm_に固執しているの?なぜl_(ローカル)ではないのですか?なぜafsdfjdskfjas_ではありませんか?とにかく、それはばかげた宗教的議論なので、私はこの質問に賛成票を投じます。好きなことをしてください。あなたもノックしているガイドラインは、「フィールドの命名ガイドラインが適用言っ静的なパブリックおよび保護フィールド内部およびプライベートフィールドがされている_not_ガイドラインでカバーし、パブリックまたは保護されたインスタンスフィールドはメンバーの設計ガイドラインによって許可されていません。」
アンディ

1
@BettyCrokker OK、しかし、あなたはその仮定で作られたガイドラインについて尋ねています。また、「誰も」(許容できる統計的許容範囲内)がC#コードを出力するため、その仮定を使用している可能性が高い静的ツールについても不満を言っています。どの統計分析ツールを使用しているかわかりませんが、Resharperはかなり具体的です。プライベートフィールドは "_lowerCase"です。任意のタイプのパブリックメンバーまたは「UpperCase」、およびローカルは「lowerCase」です。とにかく、「m」を保存することは実際にはかなりいいように見えます。
ケビンフィー

17

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

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

パラメーターオブジェクトを抽出し、関数を複数の単純なものに分割してみてください。保守性を考慮せずに、特徴や複雑さにinれたくない場合は、コードをリファクタリングする必要があります。

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


ドットを挿入すると、クラスまたは名前空間になります。
CodesInChaos

3
これは本当に質問に答えるとは思わない。
ウラジミールストキッチ

5
@FrankHileman実際、そうです。名前をuす理由がない理由を説明します。

2
「ugい」?この場合、意見のみの質問です。誰もがさについて異なる意見を持つことができます。ある規則を別の規則よりも優先する理由はありますが、この場合には標準的な規則はありません。
フランクヒルマン

1
@Deduplicatorの美しさは見る人の目にあります。私はかつていと考えていた慣習を、今では便利だと評価しています。
フランクヒルマン

11

なぜ開発者は名前空間ディレクティブを使用して名前空間を先頭に追加しないのですか?

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

いいえ。私たちは怠け者のタイピストですが、そういうわけではありません。

詳細を無視して抽象化に集中できるコーディングスタイルを好みます。構造の詳細を伝えるために名前を強制することは注意をそらすものです。複雑なアルゴリズムに取り組んでいるとき、私が作業しているものについて少しずつ詳細を思い出させることを主張する名前は望ましくありません。私はちょうど混乱から私を保つために名前を必要TimerDateTime。それらがどこかで互換性があるかどうか心配です。

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


2
これは質問に答えていないようです。.netのプライベートフィールドには、一般的な好みや慣習はありません。
フランクヒルマン

12
@FrankHileman一般的に、良い名前を好みます。規則は良い名前を作成しません。規約により、McOhPlease Von StopItAlreadyStineのような名前が作成されます。
candied_orange

規約は、異なる開発者のコ​​ードで作業しやすくするためのものです。あなたの答えはハンガリー人に対処しますが、私有地には慣習がないため、質問は誤った仮定に基づいています。
フランクヒルマン

7

少し拡大しましょう。

3つの一般的なプレフィックススタイルがあり、それらはすべてc#コードでときどき検出されます。

  • m_
  • _
  • この。

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

m_over を使用する利点は_、プレフィックスとして使用できない言語_と同様にc#を使用する場合、コードベース全体でプレフィックスを同じにすることができることです。* m_over の利点は、this.短くなり、誤ってプレフィックスを忘れます。

_オーバーの利点m_は、それが短くなり、プレフィックスで始まるものはすべて上部でソートされることです。ツールによってアルファベット順にソートされます。_オーバーの利点this.は、それが短く、誤ってプレフィックスを忘れないことです。

利点this.を超えるm__、あなたがコードベースでそれを使用することができるということです_m_受け入れられた普遍的な慣例ではありません。それはまた、誰も物事_m_慣習について知る必要がないことを意味します。欠点として、コンパイラはこの接頭辞を気にしないため、this.接頭辞が欠落することがあり、インジケータほど信頼性が低くなります。


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


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


1
素敵な比較。ただし、実際にはプレフィックスを使用しないことがうまく機能することがわかりました。
Phil1970

6

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

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

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

さまざまな理由で、一般的に変数プレフィックスは推奨されていないと述べました

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

2
元々、フィールドにはプレフィックスをまったく使用しませんでした。後で、IDEドロップダウンリストボックスを使用するときにすべてのフィールドがアルファベット順のメンバーリストの一番上に移動するため、他の人が使用しているのを見て、単一の「_」文字の使用に切り替えました。多くの異なる開発者によって書かれたコードを読むとき、標準的な慣習の欠如は迷惑です。
フランクヒルマン

しばらくすると、非常に多くの異なるスタイルが表示されるので、それらを無視します。あなたは常にすべてのリファクタリングされるだろうスタイル強制しようとした場合
ユアン・

4
「それらは間違っている可能性があるため、誤解を招く可能性があります」をほとんどすべてに適用すると、変数や関数に名前を付けてはならないことがすぐにわかります。そして、私はあなたの2番目の箇条書きが「あなたが作成していないクラス」と言うことになっていると推測していますか?または、私はそれを理解していません...いずれにしても、非公開フィールドに単一の下線プレフィックスを付けることは非公式の標準であるように聞こえ始めています、それはおそらく私たちが進む方向です。
ベティクロッカー

いくつかのものはm_countがメンバ変数ではないかもしれませんので、コンパイラによってチェックされますが、this.countは常になります
ユアン・

多くの社員が_を使用していますが、状況は時間とともに変化します。昨年の「ベストプラクティス」に書かれたコードは、今年の慣例と一致しないことがわかります
Ewan

4

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

count = 3;

「count」はその関数のローカル変数であり、関数の他の場所で使用される何かをしていると思います

そして、C#のスタイル規則を尊重するソースコードを読んでいるなら、あなたは絶対に正しいでしょうそのようなコードでは:

this.count = 3;

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

count = 3;

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

したがって、C#のスタイル規則は明確で明確です。プレフィックスが不要なため、プレフィックスを使用しないように強制します

著者は代わりに自分の個人的な規則を使用することを決定したソースコードについては、あなたが尋ねるべきそれらを、彼らはそうする選択をした理由は個人的に。アンダースコアなどのプレフィックスを使用せず、どちらも使用しない場合、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の場合、this.m_countと入力する必要はありません。

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

メモ帳でコードを書くときは、もっとタイピングします。オートコンプリート機能を備えたIDE、またはより優れたIntelliSenseを使用すると、this.countとの比較m_countはそれほど明確ではありません。アンダースコアの入力に必要なShift+に注意してください-

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


6
this必要なときにのみ使用すると、非常に一貫性のない感じになり、あまりにも頻繁に気を散らしてしまいます。thisプレフィックスの代わりに使用する場合は、常に使用する必要があると思います。その場合、それは接頭辞になり、を使用することもできます_
ラバーダック

1
ラバーダックは正しい。"この。" プレフィックスですが、コンパイラの意味があります。
フランクヒルマン

4

「メンバー」プレフィックスは、実装の詳細の一種です。リファクタリングの可能性を考える際に、問題の領域から技術的な解決の領域に注意をそらすことで、あなたの心を偏らせます。–私

さらに説明できますか?あなたが接頭辞を使用しない理由について私が見た唯一の理由であり、私はそれを理解していません...私がそうすべきではない理由とは異なります)–ベティ・クロッカー

私のポイントは、@ 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);
   }
} 

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

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

プレフィックスがなければ、メソッドシグネチャのみが変更されます。名前の変更はまったく必要ありませんでした。


変更時にSCM履歴が乱雑になる

また、ロジックは変更されていませんが、SCMはプレフィックスの変更をロジックの変更として記録します!SCMの歴史には、この技術的な変更が散らばっていて、何が重要かを隠し、他の(実際のロジック)変更との競合のリスクを高めています。


1

すべてのメンバー変数に_プレフィックスを使用します。私は 'this'プレフィックスが嫌いです。なぜなら、それが正しいやり方だと主張する人もいますが、それはコードベースに多くのノイズ/クラッタを追加します。Microsoftのサンプルでは、​​単一の下線も一般的な方法です。

したがって、あなたの例では私が持っているでしょう:

int _count = 10;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.