命名規則-C ++およびC#変数のアンダースコア


146

_varクラスフィールドに変数名が表示されることはよくあります。下線はどういう意味ですか?これらすべての特別な命名規則のリファレンスはありますか?



17
誤解を招くコーポレートコーディングガイドラインでは、クラスと関数が必然的に大きくなりすぎて、このような漠然とした手掛かりなしに何が何であるかを追跡できないとの信念から、メンバー変数にローカル変数と区別するためにいぼを追加することを提案しています。このような規則を提案する人々は、コードがそれらを最も必要とするものであることがよくあります。
Mike Seymour

26
@マイク-あなたの包括的な声明は真実ではありません。この規則を使用すると、メソッドをすばやくスキャンしてクラスをよく理解できるようになることがわかりました。
ChaosPandion 2010年

12
@ChaosPandion:それを包括的なステートメントとして読み取らないでください。「一部」は「すべて」を意味するものではなく、「すべてが頻繁」は「常に」を意味するものではありません。おそらく、あなたは私の経験の例外です。
Mike Seymour 2010年

17
C ++では、アンダースコアの先頭を避けます。多くのコンテキスト(つまり、グローバルスコープ、大文字が続く場合など)では、これらは実装用に予約されており、実際にマクロトランプルが発生するリスクがあります。したがって、必要に応じて、末尾をアンダースコアにします
sbi

回答:


120

下線は単なる規則です。これ以上何もない。そのため、その使用法は常に各人によって多少異なります。問題の2つの言語でこれらを理解する方法を次に示します。

C ++では、アンダースコアは通常、プライベートメンバー変数を示します。

通常、C#では、パブリックプロパティの基になるプライベートメンバー変数を定義するときにのみ使用されます。他のプライベートメンバー変数にはアンダースコアはありません。ただし、この使用法は、自動プロパティの出現により主に道端に行きました。

前:

private string _name;
public string Name
{
    get { return this._name; }
    set { this._name = value; }
}

後:

public string Name { get; set; }

11
プロパティを不変にしたいチームを除きます。
ChaosPandion 2010年

11
アンダースコアで始まる識別子はコンパイラ用に予約されています。プレフィックスの下線を使用すると、コンパイラシンボルと競合する可能性があります。
Thomas Matthews

12
@Thomas Matthews-C#ではありません。
EMP

11
@ChaosPandion「不変」とは実際には「読み取り専用」であると想定していますpublic string Name { get; private set; }。この場合、を使用できます。確かに、完全に不変ではありませんが、存在します。
jdmichal

7
@Thomasクラスコンテキストでは、アンダースコアで始まり、C ++で予約されている大文字の後に続く識別子。_var予約されていません。
タイラーマクヘンリー2010

84

C ++では、変数名またはパラメーター名の前にUNDERSCORESを使用しないことがベストプラクティスです。

アンダースコアまたはダブルアンダースコアで始まる名前は、C ++の実装者向けに予約されています。下線付きの名前は、ライブラリが機能するために予約されています。

C ++コーディング標準を読んだ場合、最初のページに次のように表示されます。

「命名を過度に規制しないでください。ただし、一貫した命名規則を使用してください:必須事項は2つしかありません。(p2、C ++コーディング標準、Herb SutterおよびAndrei Alexandrescu)

より具体的には、ISOワーキングドラフトは実際のルールを述べています。

さらに、一部の識別子はC ++実装で使用するために予約されており、それ以外では使用されません。診断は必要ありません。(a)二重アンダースコア__を含む、またはアンダースコアで始まり、その後に大文字が続く各識別子は、あらゆる使用のために実装用に予約されています。(b)アンダースコアで始まる各識別子は、グローバル名前空間の名前として使用するために実装に予約されています。

上記の制限のいずれかに誤って移動した場合に備えて、シンボルをアンダースコアで開始しないことをお勧めします。

このようなアンダースコアの使用がソフトウェアの開発時に悲惨である理由を、あなたはそれで確かめることができます:

次のような単純なhelloWorld.cppプログラムをコンパイルしてみてください。

g++ -E helloWorld.cpp

あなたはバックグラウンドで起こるすべてを見るでしょう。これがスニペットです:

   ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
   try
     {
       __streambuf_type* __sb = this->rdbuf();
       if (__sb)
  {
    if (__sb->pubsync() == -1)
      __err |= ios_base::badbit;
    else
      __ret = 0;
  }

二重下線で始まる名前の数がわかります!

また、仮想メンバー関数を見ると、* _ vptrは、クラスで1つ以上の仮想メンバー関数を使用すると自動的に作成される仮想テーブル用に生成されたポインターであることがわかります。しかし、それは別の話です...

アンダースコアを使用すると、競合の問題が発生する可能性があり、手遅れになるまで、その原因となっているアイデアがまったくなくなります。


4
グローバルスコープでもファイルスコープでもない名前で、アンダースコアと小文字で始まる名前は問題ありませんか?特定のケースでは非常にクリーンであるため、私はこれを常に実行しています。例:void A :: set_size(int _size){size = _size; }。このような些細な用途ではどうしますか?
トゥクラ2016年

3
アンダースコアの後に小文字を続けることは、私が信じている非グローバル/ファイルスコープで許可されています。標準でそれがそうではないと言うところを私に示すことができますか?末尾のアンダースコアの問題は、メンバー変数にすでに使用していることです。だから私は関数「int size();」を持っているかもしれません メンバー変数 'int size_;' 引数 'int _size'。これは物事をうまくカバーする傾向があり、私はより良い代替案を見たことがありません。大文字のfuncsは、STLで動作するジェネリックでは使用できません。C#の人々が好む 'this.size'スタイルは、常に醜いメンバーアクセスに使用しない限り、エラーが発生しやすいようです。
トゥクラ2016年

7
下線や小文字を使用したくない人がいるのは、合法なものを明確に保つのに苦労しているためです。C ++標準では、一部の作成者が使用しないことを推奨している場合でも、それを許可しています。私にとって、それは完全に合法であり、留保されていないため、リスクがあると考える理由は何もありません。ご意見をいただきありがとうございます。
トゥクラ2016年

3
@tukra:完全に合法ではありません。C ++標準は、単一のアンダースコアの後にローカルスコープの小文字を使用することのみが許可されています。幸運を!:-)
コンスタンチノスグリノス2016年

4
ごめんなさい。私たちは過去の資格を繰り返す必要があると思っていました。アンダースコアで始まり、その後に小文字が続くC ++識別子は、ファイルスコープ以外のすべてのスコープで使用できます。これは、関数、関数プロトタイプ、クラス、構造体、共用体、列挙型、および名前空間に入れるすべてのものにおいて安全で合法です。すべてのコードを名前空間に配置するという一般的な慣習に従っている場合は、完全に安全です。
トゥクラ2016年

45

実際、_var規約はC#やC ++ではなくVBから来ています(m _、...は別のものです)。

これは、プロパティを宣言するときのVBの大文字と小文字の区別を克服するために来ました。

例えば、そのようなコードは、それが考慮されるためVBは不可能であるuserUser同じ識別子として

Private user As String

Public Property User As String
  Get
    Return user
  End Get
  Set(ByVal Value As String)
    user = value
  End Set
End Property

したがって、これを克服するために、一部の人はこのようにするために '_'をプライベートフィールドに追加する規則を使用しました

Private _user As String

Public Property User As String
  Get
    Return _user
  End Get
  Set(ByVal Value As String)
    _user = value
  End Set
End Property

多くの規則は.Netに関するものであり、C#とVB.NETの規則の間の一定性を保つために、同じ規則を使用しています。

私が言っていることのリファレンスを見つけました:http : //10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices

先行アンダースコア付きのキャメルケース。VB.NETでは、常に「保護」または「プライベート」を示し、「Dim」は使用しないでください。"m_"の使用はお勧めできません。プロパティと大文字小文字のみが異なる変数名を使用することはお勧めできません。特に、保護された変数はコンプライアンスに違反しているため、VB.NETでプログラムすると、あなたの人生が苦痛になります。メンバーに、アクセサー/ミューテータープロパティとは異なる名前を付ける必要があります。ここにあるすべての項目の中で、先頭のアンダースコアは本当に唯一の物議を醸すものです。個人的には、プライベート変数をアンダースコアなしのラクダの場合よりも個人的に好むので、変数名を「this」で修飾する必要はありません。コンストラクタや他の場所で名前の衝突が発生する可能性がある場所のパラメータと区別するため。VB.NETでは大文字と小文字が区別されないため、アクセサープロパティは通常、アンダースコアを除いてプライベートメンバー変数と同じ名前になるため、これはさらに重要です。m_に関する限り、それはまさに美学に関するものです。変数名に穴があるように見えるので、私(および他の多くの人)はm_ uglyを見つけます。それはほとんど不快です。私はいつもVB6でこれを使用していましたが、それは変数に先行アンダースコアを付けることができないためでした。私はそれが消えるのを見ることが幸せでした。Microsoftは、m_(およびストレート_)をコードで両方実行した場合でも、それらに対して推奨しています。また、まっすぐな「m」を前に付けることもできます。もちろん、これらは主にC#でコーディングするため、プロパティとは大文字と小文字のみが異なるプライベートメンバーを持つことができます。VBの人々は別のことをしなければなりません。言語ごとの特殊なケースを考え出すよりも、それをサポートするすべての言語の主要なアンダースコアをお勧めします。クラスを完全にCLS準拠にしたい場合は、C#で保護されたメンバー変数のプレフィックスを省略できます。ただし、実際には、保護されている可能性のあるすべてのメンバー変数をプライベートにし、代わりに保護されたアクセサーとミューテーターを提供するため、これについて心配することはありません。理由:簡単に言うと、この規則は単純(1文字)で読みやすく(他の先頭の文字に気を取られない)、プロシージャレベルの変数やクラスレベルのプロパティとの名前の衝突を回避できます。クラスレベルのプロパティ。それをサポートするすべての言語について、主要なアンダースコアをお勧めします。クラスを完全にCLS準拠にしたい場合は、C#で保護されたメンバー変数のプレフィックスを省略できます。ただし、実際には、保護されている可能性のあるすべてのメンバー変数をプライベートにし、代わりに保護されたアクセサーとミューテーターを提供するため、これについて心配することはありません。理由:簡単に言うと、この規則は単純(1文字)で読みやすく(他の先頭の文字に気を取られない)、プロシージャレベルの変数やクラスレベルのプロパティとの名前の衝突を回避できます。クラスレベルのプロパティ。それをサポートするすべての言語について、主要なアンダースコアをお勧めします。クラスを完全にCLS準拠にしたい場合は、C#で保護されたメンバー変数のプレフィックスを省略できます。ただし、実際には、保護されている可能性のあるすべてのメンバー変数をプライベートに保ち、代わりに保護されたアクセサーとミューテーターを提供するため、これについて心配することはありません。理由:簡単に言うと、この規則は単純(1文字)で読みやすく(他の先頭の文字に気を取られない)、プロシージャレベルの変数やクラスレベルのプロパティとの名前の衝突を回避できます。クラスレベルのプロパティ。保護されている可能性のあるすべてのメンバー変数をプライベートに保ち、代わりに保護されたアクセサーとミューテーターを提供するので、これについて心配する必要はありません。理由:簡単に言うと、この規則は単純(1文字)で読みやすく(他の先頭の文字に気を取られない)、プロシージャレベルの変数やクラスレベルのプロパティとの名前の衝突を回避できます。クラスレベルのプロパティ。保護されている可能性のあるすべてのメンバー変数をプライベートに保ち、代わりに保護されたアクセサーとミューテーターを提供するので、これについて心配する必要はありません。理由:簡単に言うと、この規則は単純(1文字)で読みやすく(他の先頭の文字に気を取られない)、プロシージャレベルの変数やクラスレベルのプロパティとの名前の衝突を回避できます。クラスレベルのプロパティ。


6

最初のコメンター(R Samuel Klatchko)が言及:C ++識別子でアンダースコアを使用する場合のルールは何ですか?これは、C ++の下線に関する質問に答えます。アンダースコアはコンパイラの実装者用に予約されているため、通常、先頭のアンダースコアを使用することは想定されていません。あなたが見て_varいるコードは、おそらくレガシーコードか、または主要なアンダースコアを避けなかった古い命名システムを使用して育った誰かによって書かれたコードのいずれかです。

他の回答が述べているように、これはクラスメンバー変数を識別するためにC ++で使用されていました。ただし、デコレータや構文に関する限り、特別な意味はありません。したがって、使用したい場合はコンパイルされます。

C#のディスカッションは他にお任せします。


5

_varには意味がなく、変数がプライベートメンバー変数であることを簡単に区別できるようにする目的でのみ機能します。

C ++では、_var規則の使用は不適切な形式です。これは、識別子の前にあるアンダースコアの使用を管理する規則があるためです。_varはグローバル識別子として予約されていますが、_Var(アンダースコア+大文字)はいつでも予約されています。これが、C ++では、代わりにvar_規則を使用している人がいる理由です。


4

独自のコーディングガイドラインを作成できます。チームの他のメンバーに明確なドキュメントを書いてください。

_fieldを使用すると、Intelilsenseは_と入力するだけですべてのクラス変数をフィルターできます。

通常はBrad Adamsのガイドラインに従いますが、アンダースコアは使用しないことをお勧めします。


2

MicrosoftのC#の命名基準では、変数とパラメーターはIEの 小文字のキャメルケース形式を使用する必要があるとしていますparamName。フィールドが同じ形式に従うことをするための標準も呼び出しますが、多くのチームが分かりやすく改善するために、アンダースコアの接頭辞を求めるように、これは不明確なコードにつながることができますIEを: _fieldName


2

C#では、Microsoft フレームワーク設計ガイドラインは、パブリックメンバーにアンダースコア文字を使用しないことを推奨しています。以下のためのプライベートメンバー、アンダースコアは使用にOKです。実際、Jeffrey Richter(ガイドラインでよく引用されます)は、たとえばm_を使用し、プライベート静的メンバーには "s_"を使用します。

個人的には、_を使用してプライベートメンバーをマークしています。"m_"と "s_"はハンガリー語表記に近づいています。これは.NETでは不快なだけでなく、非常に冗長になる可能性があり、多くのメンバーを含むクラスではアルファベット順にクイックアイスキャンを実行するのが困難です(すべての変数がm_で始まる10個の変数を想像してください)。 。


ハンガリー語の表記はタイプを示しているので、m / sがそれに近いとは言えません。
ジェリーニクソン

@ JerryNixon-MSFTハンガリーの概念に関しては、変数のデータ型と変数の可視性の型を同じものとして識別しますか?
Necro、

1

私は、クラスのメンバー変数に_var命名を使用しています。私が行う主な理由は2つあります。

1)後でコードを読み取るときに、クラス変数とローカル関数変数を追跡するのに役立ちます。

2)クラス変数を探すときにIntellisense(または他のコード補完システム)で役立ちます。最初の文字を知っているだけで、使用可能な変数とメソッドのリストをフィルタリングできます。


1
varがローカルで定義されているかどうかを確認するために、ホバーインテリセンスまたはスキャンに依存することは、より大きな方法の面倒です。また、あなたが言及したのと同じ理由で、静的には "__"を好むが、現在は好まれていない。
crokusek 2013

1

CおよびC ++言語に関する限り、名前の下線(先頭、中間、末尾)に特別な意味はありません。それは単なる有効な変数名文字です。「規約」は、コーディングコミュニティ内のコーディング慣行に由来します。

上記のさまざまな例ですでに示したように、最初の_は、C ++のクラスのプライベートまたは保護されたメンバーを意味する場合があります。

ちょっとした雑学かもしれない歴史を少しだけお話ししましょう。UNIXでは、コアCライブラリ関数と、カーネル関数をユーザー空間に公開するカーネルバックエンドがある場合、_は、何もせずにカーネル関数を直接呼び出す関数スタブの前にスタックします。最も有名でおなじみのこの例は、BSDおよびSysVタイプのカーネルでのexit()と_exit()です。exit()は、カーネルの出口サービスを呼び出す前にユーザー空間の処理を実行しますが、_exitはカーネルの出口サービスにマップするだけです。

したがって、_は「ローカル」のものに使用され、この場合、ローカルはマシンローカルです。通常、_functions()は移植可能ではありませんでした。そのため、さまざまなプラットフォーム間で同じ動作を期待するべきではありません。

次に、_のような変数名

int _foo;

心理的には、_は最初にタイプしなければならないのは奇妙なことです。したがって、他のものとの衝突の可能性が低い変数名を作成する場合は、特に、プリプロセッサ置換を処理するときに、_の使用を検討してください。

私の基本的なアドバイスは、コーディングコミュニティの慣例に常に従うことです。これにより、より効果的にコラボレーションできるようになります。


0

それは単にそれがクラスのメンバーフィールドであることを意味します。


0

特定の単一の命名規則はありませんが、私はプライベートメンバーに対してそれを見てきました。


0

多くの人は、アンダースコアが前に付いたプライベートフィールドを持ちたいと思っています。これは単なる命名規則です。

C#の「公式」の命名規則では、プライベートフィールドの単純な小文字の名前(アンダースコアなし)が規定されています。

アンダースコアは非常に広く使用されていますが、C ++の標準規則については知りません。


0

これは、一部のプログラマーがクラスのメンバーや他の種類の変数(パラメーター、関数のローカルなど)を操作するときにそれを明確にするために使用する慣例にすぎません。メンバー変数でも広く使用されているもう1つの規則は、名前の前に「m_」を付けることです。

とにかく、これらは単なる慣例であり、それらすべての単一のソースは見つかりません。それらはスタイルの問題であり、各プログラミングチーム、プロジェクト、または会社は独自のものを持っています(あるいは持っていません)。


0

コードをVB.NETからも拡張可能にする必要がある場合は、C#で使用する完全に正当な理由があります。(そうでなければ、私はしません。)

VB.NETは大文字と小文字を区別しないためfield、このコードで保護されたメンバーにアクセスする簡単な方法はありません。

public class CSharpClass
{
    protected int field;
    public int Field { get { return field; } }
}

たとえば、これはフィールドではなくプロパティゲッターにアクセスします。

Public Class VBClass
    Inherits CSharpClass

    Function Test() As Integer
        Return Field
    End Function

End Class

一体、field小文字で書くことさえできません-VS 2010はそれを修正し続けます。

VB.NETの派生クラスに簡単にアクセスできるようにするには、別の命名規則を考え出す必要があります。アンダースコアのプレフィックスは、おそらく最も煩わしくなく、最も「歴史的に受け入れられている」アンダースコアです。


0

this.foobarbazのように "this"を使用する表記は、C#クラスメンバー変数に使用できるようになりました。古い「m_」または単に「__」表記を置き換えます。何が参照されているかは間違いないため、コードが読みやすくなります。


0

私の経験から(確かに制限があります)、アンダースコアはプライベートメンバー変数であることを示します。ゴラムが言ったように、これはチームに依存します。


0

古い質問、新しい答え(C#)。

C#でのアンダースコアのもう1つの使用法は、ASP NET CoreのDI(依存性注入)です。readonly構築中に注入されたインターフェイスに割り当てられたクラスのプライベート変数は、アンダースコアで始まる必要があります。クラスのすべてのプライベートメンバーにアンダースコアを使用するかどうかは議論の余地があると思います(ただし、Microsoft自体がアンダースコアを使用します)が、これは確かです。

private readonly ILogger<MyDependency> _logger;

public MyDependency(ILogger<MyDependency> logger)
{
    _logger = logger;
}

-2

このような命名規則は、コード、特に自分のものではないコードを読むときに役立ちます。強力な命名規則は、特定のメンバーが定義されている場所、メンバーの種類などを示すのに役立ちます。ほとんどの開発チームは、単純な命名規則を採用し、メンバーフィールドの先頭にアンダースコア(_fieldName)を付けます。過去には、C#に次の命名規則を使用しました(これは、.NETフレームワークコードのMicrosoftの規則に基づいており、Reflectorで確認できます)。

インスタンスフィールド: m_fieldName
静的フィールド: s_fieldName
Public / Protected / Internal Member: PascalCasedName()
Private Member: camelCasedName()

これは、なじみのないコードを非常にすばやく読み取るときに、メンバーの構造、使用、アクセシビリティ、および場所を理解するのに役立ちます。


3
実際、マイクロソフトでは、m_、s_プレフィックスの使用を推奨していません。フィールド名に接頭辞を使用しないでください。たとえば、静的フィールドと非静的フィールドを区別するためにg_またはs_を使用しないでください。 msdn.microsoft.com/en-us/library/ms229012.aspx
Zied

1
先ほど言ったように、Reflectorでソースコードを確認してください。あなたは彼らが自分たちの推薦をどれだけ削っているかに驚くでしょう。;)私の投稿で述べたように、コードの読みやすさを向上させるのに役立ちます。私の最後のチームは、上記の命名規則を非常に気に入っています。
jrista
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.