下線を引くか、下線を引かないか、それが問題です


130

バイナリバージョンが他のフレームワーク言語で使用される場合、C#でプライベートフィールドの先頭にアンダースコアを付けないことで問題はありますか?たとえば、C#では大文字と小文字が区別されるため、フィールド "foo"とパブリックプロパティ "Foo"を呼び出すことができ、正常に機能します。

これは持っているだろう任意の名前がケーシングによってのみ区別される場合は任意のCLS準拠(または他の)問題によって、このようVB.NETなど、大文字と小文字を区別しない言語に効果があるのだろうか?


18
アンダースコアの接頭辞BTWの目的は、ケースの問題を処理することではありません。コードを読み取るときに、フィールドとローカルを簡単かつ視覚的に区別できるようにする必要があります。C#とVBの両方で使用します。
Neil Hewitt、

2
@NeilHewitt:まあ、それはまた、関数パラメーターがメンバー変数と競合するのを防ぎますthis。編集:私は4年前のコメントに返信しました...
Ed S.

明確にするために、公式標準は_camelCase(読み取り専用)github.com/dotnet/corefx/blob/master/Documentation/…です
Chris Marisic

私はプライベートバッキングストアには_camelCaseを好みます。つまり、プロパティを通じて割り当てられ、アクセスされるデータを保持するプライベートフィールド。自動プロパティは、クラス定義で既知の値に初期化できないため、好きではありません。セッターで副作用が必要な場合は、明示的に宣言されたバッキングストアが必要です。残念ながら、これはc#エディターで^ R ^ Eを使用するとリファクタリングされるため、毎回追加する必要があります。
TomXP411 2019

回答:


46

効果はありません。

CLS準拠のライブラリを作成するための推奨事項の一部は、ケースによってのみ異なる2つのパブリック/保護されたエンティティを持たないことです。たとえば、

public void foo() {...}

そして

public void Foo() {...}

ライブラリのユーザーがプライベートアイテムを利用できないため、あなたが説明していることは問題ではありません


1
効果はありませんが、それでも私が不快に思う慣習です。大文字と小文字が異なるだけで混乱するためのレシピだからです。唯一の違いが初期資本である場合、読み間違えやタイプミスが発生しやすくなります。
ChrisA、

2
PS個人的には、C#ではアンダースコアを付けません。私にとってそれは個人的な好みであり、宗教的信念ではありません
Binary Worrier

1
私は両方の方法を実行してきました。知識に基づいて、1つですべてを解決したいと思いました:P
TheCodeJunkie 2009年

46
下線を使用しています。それらを引数やローカル変数から区別する方が簡単です。
Rinat Abdullin、

4
私はプライベートフィールドにのみ_を使用していますが、3.5のautoプロパティのため、プライベートフィールドはほとんどありません。一般に、プライベートフィールドがあるのは、非プリミティブ型に遅延読み込みを実装する場合だけです。
Chris Marisic 2009年

278

重要な更新(2016年4月12日):

.NET CoreFXチームの内部標準は、理由に関する洞察を与えることなく、アンダースコア表記使用することを主張していることが注目されました。我々はルール#3をよく見ればしかし、それはのシステムがあることが明らかになり_t_s_なぜ示唆プレフィックス_最初の場所に選ばれましたが。

  1. 私たちは、使用し_camelCase、内部および民間分野のため、可能であれば読み取り専用使用します。プレフィックスインスタンスフィールドには_、静的フィールドにはs_、スレッド静的フィールドにはを付けt_ます。静的フィールドで使用した場合、readonly後に来る必要がありますstatic(つまりstatic readonlyませんreadonly static)。
  2. this.どうしても必要な場合以外は避けます。

したがって、.NET CoreFXチームがパフォーマンスクリティカルなマルチスレッドのシステムレベルのコード取り組んでいる場合は、次のことを強くお勧めします。

  • コーディング標準に準拠し、
  • アンダースコア表記を使用し、
  • これ以上この回答を読まないでください

そうでなければ読んでください...

元の答え:

まず、私たちが話していることについて合意しましょう。問題は、可視性修飾子が許可する場合に、クラス/サブクラスの非静的メソッドおよびコンストラクター内からインスタンスメンバーにアクセスする方法です。

アンダースコア表記

  • プライベートフィールドの名前に「_」プレフィックスを使用することを提案します
  • また、絶対に必要な場合を除いて、「this」は使用しないでください。

この表記

  • 常に「これ」を使用することをお勧めします。インスタンスメンバーにアクセスする

なぜこの表記が存在するのですか?

これがあなたのやり方だから

  • 同じ名前を共有する場合、フィールドからパラメータを区別する
  • 現在のインスタンスのコンテキストで作業していることを確認してください

public class Demo
{
   private String name;
   public Demo(String name) {
       this.name = name;
   }
}

なぜアンダースコア表記が存在するのですか?

「これ」と入力したくない人もいますが、フィールドとパラメータを区別する方法が必要なので、フィールドの前に「_」を使用することに同意しました

public class Demo
{
   private String _name;
   public Demo(String name) {
      _name = name;
   }
}

個人的な好みの問題だと思うかもしれませんが、どちらも同じように良い/悪いです。ただし、この表記がアンダースコア表記に勝る特定の側面があります。

明快さ

  • アンダースコア表記は名前を混乱させる
  • この表記は名前をそのまま保持します

認知負荷

  • アンダースコア表記は一貫性がなく、フィールドを特別な方法で扱いますが、プロパティとフィールドのどちらが必要かを自問する必要があるたびに、他のメンバーで使用することはできません

  • この表記は一貫しており、考える必要はありません。常に「this」を使用して任意のメンバーを参照します

更新:指摘されたように、以下は有利な点ではありません

メンテナンス

  • アンダースコア表記では_、リファクタリング中も注意を払う必要があります。たとえば、フィールドをプロパティに変更する(remove _)またはその逆(add _)などです。

  • この表記にはそのような問題はありません

オートコンプリート

インスタンスメンバーのリストを表示する必要がある場合:

  • 「_」を入力すると、オートコンプリートポップアップにプライベートフィールドと、残りのインスタンスメンバーと混合したリンクアセンブリから利用可能なすべてのタイプが表示されるため、アンダースコア表記はあまり役に立ちません
  • this-notationは明確な答えを与えます。「this」と入力すると、表示されるのはメンバーのリストだけで、それ以外は何も表示されません。

あいまいさ

Intellisenseの助けなしにコードを処理しなければならない場合があります。たとえば、コードレビューを行ったり、ソースコードをオンラインで閲覧したりする場合です。

  • underscore-notationがあいまいです:Something.SomethingElseが表示されても、Somethingがクラスであり、SomethingElseがその静的プロパティであるかどうかはわかりません...または、Somethingは、SomethingElseの独自のプロパティを持つ現在のインスタンスプロパティです

  • この表記は明確です。Something.SomethingElseが表示された場合、それは静的プロパティを持つクラスのみを意味し、this.Something.SomethingElseが表示された場合、Somethingがメンバーであり、SomethingElseがそのプロパティであることがわかります。

拡張メソッド

「this」を使用せずにインスタンス自体で拡張メソッドを使用することはできません。

  • アンダースコア表記では、「this」を使用しないことが必要ですが、拡張メソッドでは、
  • この表記はためらいからあなたを救います、あなたはいつも「これ」の期間を使います。

Visual Studioのサポート

  • underscore-notationにはVisual Studioの組み込みサポートがありません
  • この表記は、Visual Studioによって自然にサポートされます。

    1. "この。" 資格非静的メソッドで使用されるすべての非静的フィールドをthis.、C#で前置することを推奨

公式の推奨事項

特にC#では、「アンダースコアを使用しない」と明記されている多くの公式ガイドラインがあります。


22
これは素晴らしい答えです。このすべての情報をまとめるために時間を割いていただきありがとうございます。
Tigran 2014年

5
C ++では言語と標準ライブラリの使用法のためにアンダースコアで始まる識別子を予約するため、C ++からのものではありません。
Rob G

7
パフォーマンスが重要なマルチスレッドのシステムレベルのコードと他のコードを区別するのはなぜですか?_camelCase私のコードがパフォーマンスクリティカル/システムレベルのコードである場合、を使用するとどのように役立ちますか?
BornToCode 2016

6
アンダースコアの使用は、パフォーマンスが重要なマルチスレッドコードまたはシステムレベルのコードの記述とは関係ありません。重要なのは一貫性であり、CoreFXチームは特定の規約に同意した単なるチームです。これは素晴らしい答えであり、命名規則を比較する非常に優れた分析に裏付けられていますが、「CoreFXチームが言うのでアンダースコアの方が優れている」という追加部分は本当に品質を低下させると思います。
–ŞafakGür2017

5
私の問題は、論理的な推論を理解していることです。 en.wikipedia.org/wiki/Inference しかし、ちょっと、それはみんなのためではありません。
user603563

67

Microsoft StyleCopヘルプファイルから取得:

TypeName: FieldNamesMustNotBeginWithUnderscore

CheckId: SA1309

原因: C#のフィールド名はアンダースコアで始まります。

ルールの説明:

このルールの違反は、フィールド名がアンダースコアで始まる場合に発生します。

デフォルトでは、StyleCopは、アンダースコアやm_などを使用してローカルクラスフィールドをマークし、「this」を優先します。接頭辞。「これ」を使用する利点。これは、フィールドだけでなく、メソッド、プロパティなどを含むすべての要素タイプに等しく適用され、コードの表示に使用されているエディターに関係なく、クラスメンバーへのすべての呼び出しを即座に認識できることです。もう1つの利点は、インスタンスメンバーと静的メンバーをすばやく認識できる区別ができることです。

フィールドまたは変数の名前がWin32またはCOMに関連付けられたアイテムの名前と一致することが意図されているため、アンダースコアで始める必要がある場合は、フィールドまたは変数を特別なNativeMethodsクラス内に配置します。NativeMethodsクラスは、NativeMethodsで終わる名前を含む任意のクラスであり、Win32またはCOMラッパーのプレースホルダーとして意図されています。アイテムがNativeMethodsクラス内に配置されている場合、StyleCopはこの違反を無視します。

異なるルールの説明は、上記に加えて、プライベートフィールドを小文字で開始し、パブリックフィールドを大文字で開始することを推奨していることを示しています。

編集:フォローアップとして、StyleCopのプロジェクトページはhttps://github.com/DotNetAnalyzers/StyleCopAnalyzersにあります。ヘルプファイルを読むと、さまざまなスタイルのルールを提案する理由がわかります。


7
これは主に「ベストプラクティス」のようなものです。ルールに記載されているように、「this」の接頭辞は非静的メンバーに適用できますが、その他の接頭辞は言語構文ルールにより適用できない場合があります。「this」キーワードは、目的の宛先を簡単に明確にします。
スコットドーマン、

5
私はまた、問題を回避するための人為的な方法よりも、問題に対するこの言語の意図された解決策( "this")を支持します。
ガラクトール、2011年

10
同じソフトウェアには、大文字と小文字だけが異なる2つのフィールドを持たないようにするというルールもあります。それでは、パブリックプロパティでラップされた保護された変数をどのように処理しますか?
リリスリバー

5
「アンダースコアなし」の問題の唯一の問題は、(Web)フォームなどに対してプログラミングするときに、「これ」だけを使用しても、定義したプライベートフィールドにフィルターをかけることができず、代わりに上記のオブジェクトに含まれる800万の他のプロパティの巨大なリスト。

14
StyleCopはthis、クラスメンバーを参照するときに一貫して使用すると、を検索するだけですべてのクラスメンバーへのすべての呼び出しを見つけることができると言っているようですthis。私はそれについて議論することはできませんが、私がそれをする必要があった時期を考えることもできません。私がやりたい最後のことは、コードに退屈なコードを追加し、コードを散らかしてthisほとんどハンガリー語です)、ほとんど実用的な利益を得られないことです。実際、コードの行を見ると、大文字またはアンダースコアで始まるものはすべてクラスメンバーであり、小文字はすべてローカルです。
devuxer 2012

27

ここではプライベートフィールドについて説明しているため、クラスのユーザーには影響しません。

ただし、プライベートフィールドにはアンダースコアを使用することをお勧めします。これにより、コードが理解しやすくなる場合があります。例:

private int foo;
public void SetFoo(int foo)
{
  // you have to prefix the private field with "this."
  this.foo = foo;

  // imagine there's lots of code here,
  // so you can't see the method signature



  // when reading the following code, you can't be sure what foo is
  // is it a private field, or a method-argument (or a local variable)??
  if (foo == x)
  {
    ..
  }
}

私たちのチームでは、プライベートフィールドには常にアンダースコアプレフィックスを使用しています。したがって、コードを読み取るときに、プライベートフィールドを非常に簡単に識別して、ローカルや引数と区別することができます。ある意味で、アンダースコアは「this」の省略形と見なすことができます。


14
ええと、フィールド、プロパティ、またはメソッドにアクセスするかどうかに関係なく、常に「this」を前に付けます。
TheCodeJunkie 2009年

9
私にとって、下線は「これ」の簡略表記のようなものです。
M4N 2009年

2
R#では、パラメーターfooを呼び出さないことをお勧めします。Set Fooに使用されることがわかっているので、それを 'value'と呼ばないでください。
thinkbeforecoding 2009年

17
@Martin:「this」の省略形としてのアンダースコアの問題は、「this」ができる間、必ずしもすべてのクラスメンバーに適用できるわけではないということです。「this」キーワードを使用すると、コードの読み取りがはるかに簡単/わかりやすくなります。あなたの例では、if(foo == x)は常にパラメーターfooを参照します。
スコットドーマン

3
@TheCodeJunkie:コードベースの冗長な文字がたくさんあります。
Ed S.

15

それ以来、非常に具体的で意味のないスタイルルールのある環境で作業した後、独自のスタイルを作成しました。これは、私が何度もめくったタイプの1つです。私は最終的にプライベートフィールドを常に_field、ローカル変数に_を含まない、小文字にすることを決定しました。コントロールの変数名はハンガリー語表記に緩やかに従い、パラメーターは通常camelCaseになります。

this.私の意見では、コードノイズが多すぎるというキーワードを嫌っています。私はリシャーパーの冗長なこれを削除するのが大好きです。キーワード。

6年の更新:Dictionary<TKey,T>同時アクセスの特定の使用法について 内部を分析し、プライベートフィールドをローカル変数であると誤って読みました。プライベートフィールドは、ローカル変数と同じ命名規則であってはなりません。アンダースコアがあった場合、それは信じられないほど明白だったでしょう。


18
thisキーワードは、現在のオブジェクトへの保証の参照です。アンダースコアではそれは得られません。嫌いにする必要はありませんthis
Jason S

15
なぜ「標準」を発明するのか。'この。' オブジェクトがインスタンス変数「クラス」であることを通知します。クラス変数であることがわかります。それ以外はすべてスタック変数です。アンダースコアは、ハンガリー記法が現在分解されているのと同じ悪い考えの山に属しています。
Quarkly、2013年

4
@ DRAirey1はこれを見逃すのが簡単すぎる。あなたがそれを必要とするとき、あなたは状態で奇妙なことをすることになります。
Chris Marisic 2013年

3
@ChrisMarisicもちろん、の使用法についてはあなたの意見を歓迎しますが_、明らかにそうでない場合は、確立された標準としてそれを主張しないでください。
ときめき

3
「自分のスタイルを作ってみた」で迷った。
rory.ap

12

アンダースコアが好きです。小文字の名前をメソッドパラメータとして次のように使用できるからです。

public class Person
{
    string _firstName;

    public MyClass(string firstName)
    {
        _firstName = firstName;
    }

    public string FirstName
    {
        get { return _firstName; }
    }
}

39
公開文字列FirstName {get; プライベートセット; }
jason

3
thisキーワードを使用すると、メソッドパラメータとして小文字を引き続き使用できます。進行中の、常に論争の的となっている「アンダースコアかどうか」をミュートポイントにする:public MyClass(string firstName){ this.firstName = firstName; }
mateuscb 2015年

5
それは未来であり、今public string FirstName { get; }でもセッターはコンストラクターで使用できます
Chris Marisic

この例では。thisコンストラクタでのみ必要になります。他の場所で使用する必要はありません。したがってfirstName、フィールド名は非常にうまく機能します。
Thomas Eyde

9

マーティンが述べた理由と、プライベートフィールドがIntelliSenseで一緒に並べ替えられるため、プライベートフィールドの前でアンダースコアを使用することは今でも本当に好きです。これは、一般にハンガリー語の接頭表記の悪さにもかかわらずです。

しかし、最近では、理由はよくわかりませんが、プライベートメンバーにアンダースコアプレフィックスを使用することは難しいと感じています。おそらく他の誰かが知っていますか?それは単に接頭辞の原則ですか?または、コンパイルされたアセンブリなどでアンダースコアが含まれるジェネリック型の名前のマングリングに関係するものはありましたか?


4
私にとって、_はコードをすばやくスキャンするときに_wordsを散らかします。それは、単に_readするようなものではなくなり、_every _に立ち止まってそれを確認し、_一部の_sortの制御文字ではない_realizeする必要があるようになります。また、フィールド名の最初の有用な文字を1列右に押すことで、インデントを中断します。ほとんどのC ++プログラマーは信じられないほど簡潔で読みづらいシンボル/マシンのようなコードを書く傾向があり、C#コードではそれを好まないので、私は一般にC ++が嫌いです:)
Oskar Duveborn

23
私にとって、これ。コードをすばやくthis.scanningすると、this.wordsが乱雑になり、これを読み取るだけではなくなり、this.more this。停止する必要があるようになり、this.every thisになります。これを認識し、this.realizeはthis.notであり、this.sortの制御文字ではありません。私はずっと時折見つけることを好むだろう_fieldFoo_fieldBar、私の使い方がでアップ雑然としているとよりthis.fieldFoothis.fieldBarthis.プレフィックスが先頭のアンダースコアよりもはるかに不快であることがわかりました。
AggieEric 2013

私はおそらく、この経験の不一致は、スペースが許可されていない古い学校のファイルシステムまたはファイル転送プロトコルに起因する可能性があり、アンダースコアをスペースとして認識し、それによって読み取りの邪魔にならないようにユーザーを訓練しました。一方、私は最初から自分のファイル名に常にスペースを使用していたため、このようなファイル名に問題があります...
Oskar Duveborn

1
@AggieEricが頭に釘を打ちました。彼の文を読むだけで頭痛がする!私はこの問題について何年にもわたってMSの推奨に固執しようとしました、そして私はthis至る所で小さな青い言葉を読むことのSICKを得て、私はすぐにオタクの怒りの決定をしました。今、私は宗教的に使用thisONLYプロパティ参照のために、または私は明示的に区別する必要がある場合thisbase。それぞれに彼自身のものだと思います:-)
Riegardt Steyn

1
最終的には、句読文字で始まるものは読みにくくなるからだと思います。誰もが気になるようには見えませんが、句読点で始まるものを読むのは非常に不自然に感じます。コードが英語に近いほど、読みやすくなります。また、最近のIDEでは、ローカルとプライベートメンバーの色を変える可能性が高いので、ローカルメンバーとプライベートメンバーの違いを見分けるのは簡単です。
Tim Long

5

スタイルコップの推奨かどうかに関係なく、.NET Frameworkを掘り下げると、メンバー変数の多くの "_"の使用法が示されます。Style Copの作成者が何を推奨しても、それはMSの従業員の大多数が使用しているものではありません。:)だから私はアンダースコアに固執します。私は個人的にアンダースコアを使用することでミスを大幅に減らすため、これを使用します(例:this.varName = varNameの代わりにvarName = varNameを使用すると、本当に私に詰まっています)


3
アンダースコアは、.NETコアスタイルガイドにも推奨されています:github.com/dotnet/corefx/wiki/Coding-style
landoncz

3

概して、クラスレベルのフィールドは、言語の設計の誤りだと思います。C#のプロパティに独自のローカルスコープがある場合は、それを優先します。

public int Foo
{
   private int foo;
   get
   {
      return foo;
   }
   set
   {
      foo = value;
   }
}

これにより、フィールドの使用を完全に停止することができます。

プライベートフィールドの先頭にアンダースコアを付けるのは、プロパティが別のバッキングフィールドを必要とするときだけです。それは私プライベートフィールドを使用する唯一の時間でもあります。(そして、私は保護フィールド、内部フィールド、またはパブリックフィールドを決して使用しないので、フィールドのピリオドを使用するのはこのときだけです。)限り、変数がクラススコープを持つ必要がある場合、それはクラスのプロパティです。


C#のギャングは、新しいプライベートint foo {get;に同意しているようです。set;}構文砂糖。
Dana、

はい; ここで私が説明していることは、それなしではまったく機能しません。
Robert Rossney、2009年

あなたが説明しているのは「自動実装プロパティ」です。残念ながら、Visual Basic.NETでは、これは実際には「隠された」_prefix変数を背後で使用します。つまり、自動実装されたプロパティ「Public Property Foo As Integer」がある場合、メンバー変数宣言「Private _foo as整数」

いいえ、少なくとも私の例では、自動実装されたプロパティについては説明していません。C#またはVBに存在しないスコープレベルについて説明しています。VBがバッキングフィールドの名前を変更するこのような簡単な方法を選択したのは本当に残念です。C#は醜いので、誤って同じ名前の変数を作成することはありません。
Robert Rossney、2012年

3

プライベートフィールドの_fieldName表記は、簡単に解読できます。「これ」を使う。表記を壊すことは不可能です。_表記をどのように破りますか?観察する:

private void MyMethod()
{
  int _myInt = 1; 
  return; 
}

これで、命名規則に違反しましたが、コンパイルされます。私は、a)ハンガリー語ではなく、b)明示的な命名規則を使用したいと思います。私はハンガリーの命名をやめることに賛成であり、これはある意味で適格です。変数名の前にあるオブジェクトのタイプの代わりに、アクセスレベルがあります。

これをRubyと比較してください。変数@my_numberの名前はスコープに名前を結び付けており、壊れません。

編集:この答えは否定的になりました。私は気にしません、それは残ります。


11
開発者がそれに従わない可能性があると言うことは、命名規則の有効な批評ではありません。
Robert Rossney、2009年

8
うわー、あなたの「壊れやすい」の定義と私のものは、まるで正反対です。あなたのことは「故意に壊れやすい」という意味ですが、他のほとんどの人はおそらく「偶然に壊れやすい」という意味です。読みやすいコードを書くのにどちらがより適切であるかを理解するための演習として残しておきます…
Konrad Rudolph

6
@コンラッド:「読者への演習として」と言うと、大げさに聞こえます。これは数学の教科書ではありません。
jcollum 2009年

3
今は少しネガティブではありません:)流れに逆らって漕ぐかもしれませんが、アンダースコアの慣習も嫌いです。私の見解では、ハンガリー語の表記法と違いはなく、正直に言うと、目が出血します(読みやすさが損なわれます)。私たちはハンガリー記法をC#で捨てました。そして、あなたのIDEを信頼しないというこの最後の痕跡を取り除く時が来ました。
Tim Long

1
アンダースコアはC#スタイルガイドでは使用されないとMSが実際に言っていると聞きました。blogs.msdn.microsoft.com/brada/2005/01/26/…-セクション2.6-少なくともBrad Abramsが私たちに同意しているようです!
jcollum 2016年

1

アセンブリをCLS準拠にする場合は、assemblyinfoファイルでCLSCompliant属性を使用できます。次に、コンパイラーは、コードにcls準拠ではないものが含まれていると文句を言います。

次に、大文字と小文字のみが異なる2つのプロパティがある場合、コンパイラはエラーを発行します。一方、同じクラスにプライベートフィールドとパブリックプロパティがある場合は問題ありません。

(しかし、私は常にプライベートメンバーの前にアンダースコアを付けます。また、特定の変数がメンバーフィールドであることをコードを読んだときに、それを明確にするのにも役立ちます)。


0

2つの理由から、プライベートフィールドの前にアンダースコアを使用するのが好きです。1つはすでに言及されていますが、フィールドはコードおよびIntellisenseの関連プロパティから際立っています。2番目の理由は、VBとC#のどちらでコーディングしても、同じ命名規則を使用できるためです。


1
おっと、それは賢いですか?下線は、VBで「次の行に続く」という意味ではありませんか?
JBRウィルキンソン

1
下線の後にスペースが続く場合のみ。
Rob Windsor、

小文字または大文字の頭文字が私にとっては目立ちます:)
ManoDestra

0

何の影響もありません。コードがコンパイルされるとき、コンパイラーにとって重要なのはフィールド/プロパティの名前空間と可視性だけです。識別子に名前を付ける場合、アンダースコアは他の文字と同じくらい重要です。本当のトリックは、あなたとあなたの周りの人々が理解する慣習を使用することです。

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