C#编程规范.docx
- 文档编号:6845948
- 上传时间:2023-01-11
- 格式:DOCX
- 页数:21
- 大小:28.18KB
C#编程规范.docx
《C#编程规范.docx》由会员分享,可在线阅读,更多相关《C#编程规范.docx(21页珍藏版)》请在冰豆网上搜索。
C#编程规范
C#コーディング標準
初版2002年9月25日
オリジナル:
http:
//ObjectClub.esm.co.jp/eXtremeProgramming/CodingStd.doc
http:
//ObjectClub.esm.co.jp/eXtremeProgramming/CodingStdVB.doc
このドキュメントはJavaコーディング標準(オブジェクト倶楽部バージョン)、VB.NETコーディング標準をC#用に変更したもので、フリーかつAS-ISベースで提供しています。
コピー、修正、配布してかまいません。
みなさんのプロジェクトでこれをカスタマイズして使用することを歓迎します。
フィードバックを歓迎します。
ご意見などを以下のアドレスへ頂けると嬉しく思います。
フィードバック先:
extremeprogramming-jp@ObjectClub.esm.co.jp
bata@gold.ocn.ne.jp
1.方針
このコーディング標準は、ソフトウェア開発プロジェクトにおいてC#でコーディングする際のルール、推奨、および迷った時の指針を提供するものである。
標準策定の方針は、読みやすくメンテナンスしやすいコードを書くことである。
実際のコーディングにあたっては、プロジェクトメンバー全員がこのルールに合意していることが必要である。
実プロジェクトにおいては、このコーディング標準をカスタマイズして用いることを推奨する。
また、あわせて.NETFrameworkSDKヘルプ「クラスライブラリ開発者向けのデザインガイドライン」を参照することを推薦する。
※特にExtremeProgrammingプロジェクトでの利用を意識したものではなく、あらゆるC#を使ったプロジェクトでの利用を想定している。
2.ファイル構成
(1)ファイル名
publicクラスはそのクラス名の1ファイルにする。
例:
publicclassCustomerは、Customer.csに入れる。
パッケージ内の非パブリッククラスは、そのクラスが主に使われるパブリッククラスのファイルに含めて良い。
例外クラスは、1ファイルに複数クラスをまとめてもよい。
(2)ファイルの位置
プロジェクトのルートディレクトリを決め、名前空間の“.”をディレクトリ階層に置き換えた位置に入れる。
但し、ソリューション/プロジェクトに対応している名前空間の階層は、ソリューション名/プロジェクト名をディレクトリ名に使用する。
例:
名前空間:
CompanyName.OrganizationName.TechnologyName.CoreFeatureName.SubFeatureName
ソリューションSolutionNameに対応する名前空間:
TechnologyName
プロジェクトProjectNameに対応する名前空間:
CoreFeatureName
配置先:
C:
\CompanyName\OrganizationName\SolutionName\ProjectName\SubFeatureName
(3)テストクラス名
クラスClassNameのユニットテストクラス名は、ClassNameTestとする。
ソリューション毎テストはSolutionNameTestsとする。
例:
CustomerクラスならCustomerTest.csを作成
例:
CsSampleソリューションなら、CsSampleTests.csprojとする
理由:
一貫性のある名前づけ。
テストコードは使い方のサンプル、デモともなる。
(4)テストクラスの位置
テストクラスの位置は、被テストクラスと同じ階層のディレクトリまたはそのサブディレクトリに配置する。
例:
被テストクラスの位置:
C:
\CompanyName\OrganizationName\SolutionName\ProjectName
テストクラスの位置:
C:
\CompanyName\OrganizationName\SolutionName\SolutionNameTests
C:
\CompanyName\OrganizationName\SolutionName\SolutionNameTests\ProjectName
理由:
物理的に近い位置でないとメンテが忘れ去られる。
製品コードとの分離については、別のツール(NAntのbuildファイルなど)で調整可能。
3.命名規則
(5)名前空間
企業略式名.組織略式名.テクノロジー名.機能名を使用する。
また、テクノロジー名にはソリューションが、機能名にはプロジェクトが対応していること。
usingCompanyName.OrganizationName.TechnologyName.FeatureName
(6)ファイル名
パブリックなクラス名は、ファイル名と同じでなくてはならない。
(大文字小文字の区別を含めて)
(7)クラス名
先頭大文字。
あとは区切りを大文字。
classPascalCasing
(8)例外クラス名
最後をExceptionとしたクラス名。
classClassNameEndsWithException
(9)インターフェイス名
クラス名に同じ。
また常に最初にIを付ける。
interfaceINameOfInterface
また、クラスにある能力を加える様な利用の場合、その能力を示す形容詞とし、-ableを接尾にする。
例:
IEnumerable,ICloneable,IXmlSerializable,…
(10)実装クラス名
特にInterfaceと区別の必要があれば、最後にImplを付ける。
classClassNameEndsWithImpl
(11)抽象クラス名
抽象クラス名に適当な名前が無いとき、Abstractから始まりサブクラス名を連想させる名前を付ける。
abstractclassAbstractBeforeSubClassName
(12)定数(Const)
大文字もしくは大文字を“_”でつないだもの。
constintUPPERCASE=0;
constintUPPERCASE_WITH_UNDERSCORES=0;
(13)列挙型(enum)
先頭大文字。
あとは区切りを大文字。
enumPascalCasing
列挙型がビットフィールドを表すときは複数形にし、FlagsAttributeを付加する。
[Flags]enumPascalCasings
(14)列挙値
先頭大文字。
あとは区切りを大文字。
PascalCasing
(15)イベント名
先頭大文字。
あとは区切りを大文字。
eventPascalCasing()
(16)メソッド名
先頭大文字。
あとは区切りを大文字。
voidPascalCasing()
objectPascalCasing()
(17)ファクトリメソッド(オブジェクトをnewするもの)
XNewX()
XCreateX()
(18)コンバータメソッド(オブジェクトを別のオブジェクトに変換するもの)
XToX()
(19)プロパティ名
先頭大文字。
あとは区切りを大文字。
objectPascalCasing()
(20)Boolean変数を返すメソッド
Is+形容詞、Can+動詞、Has+過去分詞、三単元動詞、三単元動詞+名詞。
良い例:
boolIsEmpty()
boolCanGet()
boolHasChanged()
boolContains(objectx)
boolContainsKey(stringkey)
悪い例:
boolEmpty()//「空にする」という動詞的な意味に取れる。
boolCheckXXX()//trueがどちらの意味か分かりづらい。
理由:
if,while文等の条件が読みやすくなる。
またtrueがどちらの意味か分かりやすい。
(21)bool変数
形容詞、is+形容詞、can+動詞、has+過去分詞、三単元動詞、三単元動詞+名詞。
boolisEmpty;
booldirty;
boolcontainsMoreElements;
(22)英語と日本語
すべての識別子の名前は英語を基本とし、別に、日英対応用語辞書を作成してプロジェクトの全ライフサイクルでメンテナンスすること。
(23)名前の対称性
クラス名、メソッド名を付ける際は、以下の英語の対称性に気を付ける。
Add/Remove
Insert/Delete
Get/Set
Start/Stop
Begin/End
Send/Receive
First/Last
Get/Release
Put/Get
Up/Down
Show/Hide
Source/Target
Open/Close
Source/Destination
Increment/Decrement
Lock/Unlock
Old/New
Next/Previous
(24)ループカウンタ
スコープ(通用範囲)が狭いループカウンタにi,j,kという名前をこの順に使う。
(25)スコープが狭い名前
スコープが狭い変数名は,型名を略したものを使って良い。
例:
DataSetds=newDataSet();
(26)意味がとれる名前
変数名から役割が読み取れる名前を好め。
悪い例:
Copy(strings1,strings2)
良い例:
Copy(stringsource,stringdestination)
(27)無意味な名前
Info,Data,Temp,Str,Bufという名前は再考を要する。
悪い例:
doubletemp=Math.Sqrt(b*b-4*a*c);
良い例:
doubledeterminant=Math.Sqrt(b*b-4*a*c);
(28)private/protected/internal/protectedinternalスコープのインスタンス変数
最初小文字で、あとは区切りを大文字。
プリフィクス/サフィクスを適用する場合は、変数の読みやすさを考慮すること。
ハンガリアン表記法は使用しない。
privateobjectcamelCasing;
protectedobjectcamelCasing;
internalobjectcamelCasing;
protectedinternalobjectcamelCasing;
(29)Publicスコープのインスタンス変数
先頭大文字。
あとは区切りを大文字。
極力使用しないようにすること。
publicobjectPascalCasing;
(30)private/protected/internal/protectedinternalスコープの共有変数
最初小文字で、あとは区切りを大文字。
プリフィクス/サフィクスを適用する場合は、変数の読みやすさを考慮すること。
privatestaticobjectcamelCasing;
protectedstaticobjectcamelCasing;
internalstaticobjectcamelCasing;
protectedinternalstaticobjectcamelCasing;
(31)publicスコープの共有変数
先頭大文字。
あとは区切りを大文字。
極力使用しないようにすること。
publicstaticobjectPascalCasing;
(32)ローカル変数
最初小文字で、あとは区切りを大文字。
ハンガリアン表記法は使用しない。
objectcamelCasing;
(33)大文字小文字
大文字と小文字は別な文字として扱われるが、それのみで区別される名前をつけてはならない。
4.ガイドライン
(34)#Region/#EndRegionディレクティブ
コード領域は#Region/#EndRegionディレクティブで宣言し、その領域についての説明を含める。
例:
#Region"インスタンス変数"
privatestringname;
#EndRegion
#Region"コンストラクタ"
publicMyClass(stringname)
{
this.name=name;
}
#EndRegion
(35)メソッド/プロパティの宣言
メソッド/プロパティの宣言ではスコープを明示的に指定する。
(36)長い行
一行は最大100桁とし、それを超える場合は行を分割する。
分割の指針は、
(1)ローカル変数を利用、
(2)算術演算子/連結演算子で改行、(3)カンマで改行、(4)優先度の低い演算子の前で改行 とする。
例:
doublelength=Math.Sqrt(Math.Pow(newRandom().NextDouble(),2.0)+Math.Pow(newRandom().NextDouble(),2.0));
'方針
(1)
doublexSquared=Math.Pow(newRandom().NextDouble(),2.0);
doubleySquared=Math.Pow(newRandom().NextDouble(),2.0);
doublelength=Math.Sqrt(xSquared+ySquared);
'方針
(2)
doublelength=Math.Sqrt(Math.Pow(newRandom().NextDouble(),2.0),
Math.Pow(newRandom().NextDouble(),2.0));
'方針(3)
LongMethodSignature(value[0],value[1],value[2],
value[3],value[4],value[5]);
'方針(4)
return(thisisobj)_
||(objisClass1_
andthis.Field==obj.Field);
(37)長いクラス宣言行
クラスの宣言が長い場合はカンマ、コロンで改行とする。
例:
publicclassLongNameClassImplemenation:
AbstractImplementation,IXmlSerializable,Icloneable
ならば、
publicclassLongNameClassImplemenation:
AbstractImplementation,
IXmlSerializable,ICloneable
(38)長いメソッド宣言行
メソッドの宣言が長い場合はカンマで改行とする。
例:
publicvoidLongMethodSignature(inta,intb,intc,
intd,inte,intf)
(39)abstractClassvs.interface
抽象クラス(abstractClass)はなるべく使わず、interfaceを多用せよ。
abstractClassは、一部実装があり、一部抽象メソッドであるような場合にのみ使う。
理由:
interfaceは幾つでも継承できるが、Classは1つだけ。
1つから継承してしまうと、もう継承できずもったいない。
(40)publicVariable
インスタンス変数は、極力publicにせず、妥当なプロパティを設ける。
理由:
オブジェクト指向の標準。
クラスの内部状態に勝手にアクセスさせるのはよくない。
ただし、以下の条件をすべて満たす場合、インスタンス変数をpublicにし、直接アクセスさせてもよい。
●そのインスタンス変数が他のインスタンス変数と独立であり、単独で変更されても内部の整合性をくずさない。
●どちらにしても,get/setアクセサを書く。
●インスタンス変数の実装が将来に渡って変更されないことが根拠付けられる。
また、上記に当てはまらない場合でも、極度に速度を気にする場合は、この限りではない。
(ただし、慎重にコメントすること)
(41)初期化
初期化をあてにしない(参照がnullに初期化されているとか)。
また、2度初期化しない。
悪い例:
publicclassPoorInitialization
{
privatestringname="initial_name";
publicPoorInitialization()
{
name="initial_name";
}
}
理由:
初期化に関するバグを最小化する。
(42)static変数を避ける
static変数(クラス変数)は極力避ける。
理由:
static変数は、セミグローバルと言って良い。
より文脈依存なコードを招き、副作用を覆いかくしてしまう。
(43)privatevs.protected
privateよりは、protectedを使用する。
理由:
privateは確実にそのクラス外からの使用をシャットアウトできるが、クライアントが、より細かいチューニングをSubClass化によって行うことを出来なくしてしまう。
別法:
privateをより好んで使え。
protectedにしてしまうと以降、変更が起ったときにそれを継承している全クラスに影響が出てしまう。
(44)get/setアクセサ
無闇にインスタンス変数へのプロパティ(get/setアクセサ)を作成してpublicにすることは避ける。
その必要性を検討し、もっと意味のあるプロパティ/メソッドにする。
理由:
インスタンス変数は、他のインスタンス変数に依存していることが多い。
クラス内部の整合性を崩してはならない。
(45)変数隠し
基本クラスの変数名と、同じ変数名を使う事は避けよ。
理由:
一般的にはこれはバグである。
もし意図があるならコメントせよ。
(46)publicメソッド
クラスのpublicメソッドは、「自動販売機のインターフェイス」を目標に。
分かりやすく、使いかたを間違っても内部の整合性はこわれないように設計する。
また、可能ならば契約による設計(DesignbyContract)を行い、クラスの不変条件と共にメソッドの事前・事後条件をコードで表現せよ。
(47)状態取得と状態変更の分離
メソッドは,「1つの事」を行うように設計せよ。
特に、状態変更と状態取得の2つのサービスを1つのメソッドで行わない。
状態を変更するメソッドのreturn値はvoidにせよ.
理由1:
1つの事を行うメソッドの方が分かりやすい。
理由2:
並行性の制御、例外の安全保証がしやすい。
理由3:
サブクラス化による拡張がしやすい。
(48)thisのreturn
クライアントの便宜を考えたつもりでも、thisをreturnすることはなるべく避ける。
理由:
A.Meth1().Meth2().Meth3()というような連鎖は、一般的にSynchronization上の問題の元になる。
(49)メソッドの多重定義
引数のタイプによるメソッドのオーバーロードはなるべく避ける(引数の数が違うものはOKである)。
特に、継承と絡むと厄介である。
例:
×:
overridevoidDraw(Rectanglerectangle)
overridevoidDraw(Pointpoint)
○:
voidDrawRectangle(Rectanglerectangle)
voidDrawPoint(Pointpoint)
(50)Equals()とGetHashCode()
Object.Equals()メソッドをオーバーライドするなら、同時にGetHashCode()メソッドもオーバーライドせよ。
逆も同じ。
理由:
コンテナクラス(Hashtable)などに対応するため。
(51)Clone()
もし、Clone()メソッドが使われるようなら、ICloneableを実装し明示的にそれを書く。
例:
usingSystem;
publicclassFoo:
ICloneable
{
publicobjectICloneable.Clone()
{
FoomyFoo=(Foo)this.Clone();
//Fooクラスの属性のクローン
//...
}
}
理由:
簡易コピーではよくないケースがほとんどである。
(52)デフォルトコンストラクタ
可能ならいつでもデフォルトのコンストラクタ(引数がないもの)を用意せよ。
理由:
リフレクションを使用して、Assembly.CreateInstance(TypeName)で型名文字列からダイナミックにそのクラスを作成可能。
(53)abstractMethodinabstractclasses
abstractクラスでは、no-opのメソッドを書くより、明示的にabstractメソッドと宣言せよ。
また、共有可能なデフォルトの実装を用意できるなら、それをprotectedとし、サブクラスが1行で処理を書けるようにせよ。
理由:
.NETのIDEは、実装されていないabstractメソッドを検出できるため、単に実装を忘れていただけ、というバグを回避できる。
(54)オブジェクトの同値比較
オブジェクトの比較ではEquals()メソッドを使い、=を使うな。
特に、Stringの比較では=を使用してはならない。
理由:
もし実装者がEquals()を用意しているなら、それを使ってほしくて実装したはず。
また、Stringの比較ではOptionCompareTextに設定されていると大文字/小文字が区別されない。
理由:
ユニットテストでは、AssertEqualsがEquals()を利用しているため、簡単に同値テストが書ける。
(55)宣言と初期化
ローカル変数は、初期値と共に宣言せよ。
理由:
変数の値に関する仮定を最小化する。
悪い例:
voidf(intstart)
{
inti,j;//初期値なしの宣言
//多くのコード
//...
i=start+1;
j=i+1;
//i,jを使う
//...
}
良い例:
voidf(intstart)
{
//多くのコード
//...
inti=start
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 编程 规范
![提示](https://static.bdocx.com/images/bang_tan.gif)