前回はローカルルールとは何か?というお話をしました。今回はその中の一つをご紹介します。
Private変数にアンダーバーを付けるというものです。
クラスの中でのみ参照するprivateなフィールドは変数名の頭に「アンダーバー」を付けます。
アンダーバーを付ける利点
このローカルルールの利点はコーディング中にアンダーバーを打ち込むとprivateフィールドがインテリセンスに出てきてわかりやすいというものがあります。インテリセンスとは,コーディング中に「.」ドットを付けると候補になるメソッド名等がリストされますよね。それの事です。「a」と打ち込むと「a」で始まるものや,「a」を含む変数やメソッド名がリストされますが,アンダーバーで絞り込むことで,そのクラスで自分が宣言しているprivate変数がリストされるのでわかりやすくなります。
また,「メソッド内」の変数と「クラス変数」が区別しやすいという利点もあります。
メソッド内の変数とは,なにかメソッドを作成した場合に,そのメソッドの中でのみ使用する変数の事です。メソッドを抜けるとその変数の値も消滅します。そういったメソッド内変数と,クラス全体で保持しているprivate変数とを区別するためにアンダーバーを付けます。
メソッド内にアンダーバー付きの変数があれば,この変数はクラス全体に影響するへんすうなんだなと理解しながら解析したり,コーディングしたりできます。アンダーバー付きの変数はクラス全体に影響するので,不用意に値を書き換えてはいけないという判断ができるのです。
結構主流
このローカルルールは結構主流です。私自身,いろんなプロジェクトで見たことがあるし,マイクロソフトの複数のチームでこのローカルルールは適応されているようです。
マイクロソフトの一部のチームではstaticなprivate変数も同様に区別できるように「s_」アルファベットの小文字のエスの後にアンダーバーを付けるチームもあるようです。
確かにいいアイデアだとは思いますが,少し複雑になり,チームでの統一が難しい気もするし,あまり頻繁に遭遇するケースでもないため,私のチームでは採用していません。純粋にアンダーバーのみを付けるルールは気に入って使っています。
実演
ProductEntityというクラスの中で,今解説した内容を実際にコーディングしていきます。
namespace MX99.WinForm { class ProductEntity { private string _productName = ""; public ProductEntity() { _ } } }
ProductEntityというクラスに「_productName」というprivateフィールドを作成します。
コンストラクタを作成し,その中でアンダーバーを打ち込んでみます。するとインテリセンスの中に「_productName」が表示されます。これで,このクラスのなかのprivateフィールドにはどのようなものがあるかがすぐに判るようになります。
「メソッド内の変数とクラス変数が区別できる」という例としては次のようなものになります。
using System.Collections.Generic; namespace MX99.WinForm { class ProductEntity { private string _productName = ""; public ProductEntity() { //_ } private void GetData(List products) { foreach(var productName in products) { if(productName == "") { _productName = productName; } } } } }
最初にクラスのprivateフィールドとして「_productName」を宣言し,メソッドのGetDataの中のforeachの中で「productName」を使用しています。もし,クラスのprivateフィールドの名前がアンダーバーなしの「productName」だった場合はforeachで使う名前は別の名前にするか,もしくはprivateフィールドへのアクセスを明示的に示すために「this」が必要になります。
using System.Collections.Generic; namespace MX99.WinForm { class ProductEntity { private string productName = ""; public ProductEntity() { //_ } private void GetData(List products) { foreach(var productName in products) { if(productName == "") { this.productName = productName; } } } } }
「this.productName = productName;」といった具合に「this」を付けないとどちらの「productName」か?をコンパイラが認識できないため,コンパイルが通りません。 アンダーバーを付けていれば,メソッド内の変数とprivateフィールドが重複することはなくなるので,わかりやすくなると私は思っています。 あと,同じ意味でよく使うケースはコンストラクタの引数の問題です。
class ProductEntity { private string _productName = ""; public ProductEntity(string productName) { _productName = productName; } }
このパターンは最もよく使います。クラスを生成するときに,クラス内のprivateフィールドに値を設定するケースです。この場合も引数と同じ名前になると,privateフィールドに「this」を付ける必要が出てくるので,私はアンダーバー始まりをお勧めしています。
#02_名前の付け方
#03_名前付けのガイドライン
#04_パスカルケースとキャメルケース
#05_パスカルとキャメルの内訳
#06_パスカルとキャメルの実演
#07_2文字の略語は大文字にする
#08_名前空間のガイドライン
#09_ローカルルールについて
#10_private変数にアンダーバーを付ける
#11_コントロールの名付け
#12_クラス名とファイル名の名づけ
#13_StyleCopAnalyzersについて
#14_StyleCopAnalyzersのインストール
#15_ネームスペースの調整
#16_SA0001_プロパティのビルドのXMLでファイルを指定しておくと消える
#17_CS1591_XMLコメントなし
#18_SA1101_thisが付いていない
#19_不要なルールを非表示にする方法
#20_SA1200_usingの場所
#21_SA1400_アクセス修飾子が明示的に定義されていない
#22_その他不要なルールを非表示
#23_コンストラクタとデストラクタを作成
#24_Private変数とパラメータ変数の命名
#25_中括弧の省略禁止と改行
#26_コメントはスラッシュ4つ
#27_プロパティのXMLコメント
#28_コンストラクタやプロパティの書く順番
#29_アクセスレベルを加味した書く順番
#30_インタフェースのIとファイル名の不一致
#31_最後に