"Microsoft 基本デザイン ガイドライン規則" 規則セットを使用すると、コードの理解と使用をより簡単にすることに専念できます。 この規則セットは、プロジェクトにライブラリ コードが含まれる場合や、保守が容易なコードを実現するためにべスト プラクティスを適用する場合に使用してください。
"基本デザイン ガイドライン規則" には、"Microsoft 最小推奨規則" 規則セット内のすべての規則が含まれます。 最小規則の一覧については、「"Microsoft 最小推奨規則" コード分析規則セット」を参照してください。
"Microsoft 基本デザイン ガイドライン規則" 規則セット内のすべての規則について、以下の表で説明します。
規則 |
説明 |
---|---|
ジェネリック型の静的メンバーを呼び出すときには、その型の型引数も指定する必要があります。 推論をサポートしないジェネリック インスタンス メンバーを呼び出すときには、そのメンバーに型引数を指定する必要があります。 この 2 つの場合、型引数を指定するときに使用される構文は異なりますが、混同される可能性があります。 |
|
System.Collections.Generic.List<(Of <(T>)>) は継承ではなくパフォーマンスを目的としたジェネリック コレクションです。 このため、List には仮想メンバーは含まれません。 代わりに、継承を目的としたジェネリック コレクションを公開する必要があります。 |
|
型に void を返すデリゲートが含まれており、デリゲートのシグネチャに 2 つのパラメーター (1 つはオブジェクト、もう 1 つは EventArgs に割り当て可能な型) が含まれ、包含アセンブリの対象が .NET Framework 2.0. です。 |
|
型引数を明示的に指定するのではなく、メソッドに渡す引数の型によってジェネリック メソッドの型引数を決定する方法が推論されます。 推論を有効にするには、ジェネリック メソッドのパラメーター シグネチャに、そのメソッドの型パラメーターと同じ型のパラメーターが含まれている必要があります。 この場合、型引数を指定する必要がなくなります。 すべての型パラメーターについて推論を使用する場合、ジェネリック インスタンス メソッドを呼び出す構文と、非ジェネリック インスタンス メソッドを呼び出す構文は同じになります。これにより、ジェネリック メソッドの使用方法が単純化されます。 |
|
ジェネリック型に含まれる型パラメーターが増えれば増えるほど、それぞれの型パラメーターが表す意味を調べることや覚えることが難しくなります。 通常、List<T> のように型パラメーターが 1 つの場合や、Dictionary<TKey, TValue> のように型パラメーターが 2 つの場合、意味は明確です。 しかし、型パラメーターが 3 つ以上になると、ほとんどのユーザーには意味を把握することが困難になります。 |
|
入れ子にされた型引数は、ジェネリック型の型引数でもあります。 入れ子にされた型引数を含むシグネチャを持つメンバーを呼び出すには、ユーザーが 1 つのジェネリック型をインスタンス化し、別のジェネリック型のコンストラクターにこの型を渡す必要があります。 複雑な手順と構文が必要となるため、これは避けるようにしてください。 |
|
外部から参照できるメソッドに、System.Object 型の参照パラメーターが含まれています。 ジェネリック メソッドを使用することで、型を最初に参照パラメーターの型にキャストせずに、制約の影響を受けるすべての型をメソッドに渡すことができます。 |
|
初期化されていない列挙型の既定値は、他の値型と同様に、ゼロです。 フラグではない属性が付いた列挙型では、ゼロの値を持つメンバーを定義する必要があります。これは、既定の値を有効な列挙値にするためです。 FlagsAttribute 属性を適用した列挙型でゼロ値のメンバーを定義する場合、名前を "None" にして、列挙型に設定済みの値がないことを示します。 |
|
コレクションの操作性を拡充するために、ジェネリック コレクション インターフェイスの 1 つを実装します。 これにより、コレクションを使用してジェネリック コレクション型を設定できます。 |
|
メソッドの宣言で基本型をパラメーターとして指定すると、その基本型から派生した型は、メソッドに対応する引数として渡すことができます。 派生パラメーター型で実現する追加機能が不要である場合、基本型を使用することでメソッドをより広範囲に利用できるようになります。 |
|
抽象型上のコンストラクターは、派生型からのみ呼び出すことができます。 パブリック コンストラクターで型のインスタンスが作成され、抽象型のインスタンスは自分で作成できないため、パブリック コンストラクターが含まれる抽象型のデザインは不適切になります。 |
|
パブリック型またはプロテクト型で、等値演算子を実装しないまま、加算演算子または減算演算子を実装しています。 |
|
共通言語仕様 (CLS) には、名前付けの制約、データ型、および規則が定義されています。アセンブリを複数のプログラミング言語で使用する場合、この仕様に準拠する必要があります。 すべてのアセンブリに CLSCompliantAttribute を使用して、CLS への準拠を明示することをお勧めします。 この属性が使用されていないアセンブリは、CLS に準拠しません。 |
|
ComVisibleAttribute 属性によって、COM クライアントからマネージ コードにアクセスする方法が決まります。 アセンブリで COM の参照範囲を明示することをお勧めします。 COM の参照範囲は、アセンブリ全体に設定し、個々の型と型のメンバー用にオーバーライドできます。 この属性がない場合、アセンブリのコンテンツは COM クライアントから参照できます。 |
|
カスタム属性を定義する場合、AttributeUsageAttribute を使用してマークし、カスタム属性を適用できるソース コードの位置を示します。 属性の意味と用途によって、コード内の有効な位置が決まります。 |
|
属性では、対象に適用するときに必ず指定する必須の引数を定義できます。 この引数は、コンストラクターに位置指定パラメーターで属性を指定できるようになるため、位置指定引数とも呼ばれます。 必須のすべての引数について、対応する読み取り専用のプロパティも属性で規定する必要があります。これは、引数値を実行時に取得できるようにするためです。 また、属性ではオプションの引数も定義できます。これは名前付き引数とも呼ばれます。 この引数は、名前でコンストラクターに属性を指定するときに使用されます。また、対応する読み取り/書き込みプロパティが必要です。 |
|
インデクサー (つまり、インデックス付きのプロパティ) では、インデックスを 1 つだけ使用します。 多次元のインデクサーがあると、ライブラリの操作性が著しく低下することがあります。 |
|
パブリック メソッドまたはプロテクト メソッドに、"Get" で始まる名前が付けられ、パラメーターは使用されていません。また、配列ではない値を返します。 このメソッドは、プロパティに変更できる可能性があります。 |
|
引数の正確な数が不明で、可変個の引数が同じ型である場合、または同じ型で渡すことができる場合、引数を繰り返すのではなく、パラメーター配列を使用します。 |
|
既定のパラメーターを使用するメソッドは、共通言語仕様 (CLS) で許可されていますが、CLS では、既定のパラメーターに割り当てられた値をコンパイラで無視することも許可されています。 複数のプログラミング言語間で動作を維持するために、既定のパラメーターを使用するメソッドは、既定のパラメーターを指定したメソッドのオーバーロードで置換します。 |
|
列挙型は、関連する名前付き定数が複数定義された値型です。 名前付き定数を有意に結合できる場合、列挙型に FlagsAttribute を適用します。 |
|
列挙型は、関連する名前付き定数が複数定義された値型です。 既定で、System.Int32 データ型は、定数値を格納するために使用されます。 この基になる型を変更できる場合でも、ほとんどの場合、変更する必要はなく、推奨もされません。 |
|
この規則では、通常はイベントに使用される名前を持つメソッドを検出します。 明示的に定義された状態変化に応答してメソッドが呼び出される場合、メソッドはイベント ハンドラーから呼び出す必要があります。 メソッドを呼び出すオブジェクトは、メソッドを直接呼び出すのではなく、イベントを発生させる必要があります。 |
|
汎用的な例外はキャッチしないでください。 より具体的な例外をキャッチするか、汎用的な例外を catch ブロックの最後のステートメントでスローし直します。 |
|
コンストラクターを完全に宣言していないと、例外を正しく処理するのが困難になります。 |
|
入れ子にされた型とは、別の型のスコープ内で宣言された型のことです。 入れ子にされた型は、含まれる型のプライベート実装の詳細をカプセル化するときに便利です。 このような用途なので、入れ子にされた型は外部から参照できないようにします。 |
|
この規則では、ICollection で厳密に型指定されたメンバーを実装する必要があります。これは、ユーザーがインターフェイスに備わっている機能を使用するときに、必ずしも引数を Object 型にキャストするとは限らないためです。 この規則では、ICollection を実装する型でこの処理を行って、Object よりも厳密な型のインスタンス コレクションを管理すると想定しています。 |
|
パブリック型またはプロテクト型で System.IComparable インターフェイスを実装しています。 これによって、Object.Equals はオーバーライドされません。また、"等しい"、"等しくない"、"未満"、"より大きい" を示す言語固有の演算子はオーバーロードされません。 |
|
この規則では、IEnumerator で、厳密に型指定された形式の Current プロパティを実装する必要があります。これは、ユーザーは、インターフェイスに備わっている機能を使用するときに、必ずしも戻り値を厳密な型にキャストするとは限らないためです。 |
|
この規則では、IList で厳密に型指定されたメンバーを実装する必要があります。これは、ユーザーがインターフェイスに備わっている機能を使用するときに、必ずしも引数を System.Object 型にキャストするとは限らないためです。 |
|
型またはメンバーが System.ObsoleteAttribute 属性でマークされていますが、この属性で ObsoleteAttribute.Message プロパティが指定されていません。 ObsoleteAttribute でマークされている型またはメンバーをコンパイルすると、属性の Message プロパティが表示されます。これによって、ユーザーは旧式の型またはメンバーに関する情報を知ることができます。 |
|
インデクサー (つまり、インデックスされたプロパティ) では、インデックスに整数型または文字列型を使用します。 一般に、このような型はデータ構造のインデックス作成に使用され、ライブラリの操作性も改善されます。 Object 型の使用は、デザイン時に特定の整数型または文字列型を指定できない場合に限定してください。 |
|
読み取り専用のプロパティは許容され、必要な場合もよくあります。一方で、書き込み専用のプロパティを使用することはデザインのガイドラインで禁止されています。これは、値を設定できても値を参照できず、セキュリティが確保されないためです。 また、読み取りアクセスがないと、共有オブジェクトのステータスを参照できないため、実用性が制限されます。 |
|
参照型の場合、等値演算子は既定の実装でほぼ問題がありません。 既定で、2 つの参照が等値と見なされるのは、同じオブジェクトを参照する場合のみです。 |
|
型でプロテクト メンバーを宣言するのは、継承する型からメンバーにアクセスまたはオーバーライドできるようにするためです。 定義により、シールされた型から継承することはできません。これは、シールされた型のプロテクト メソッドを呼び出すことができないということを意味します。 |
|
型でメソッドを仮想と宣言するのは、継承する型が仮想メソッドの実装をオーバーライドできるようにするためです。 定義により、シールされた型から継承することはできません。 これにより、シールされた型の仮想メソッドの意味がなくなります。 |
|
型を名前空間内で宣言するのは、名前が衝突しないようにするためと、関連する型をオブジェクト階層形式で編成するためです。 |
|
フィールドの主な用途は、実装の詳細にする必要があります。 フィールドは private または internal にし、プロパティによって公開するようにします。 |
|
パブリック型またはプロテクト型に静的メンバーしかなく、sealed (C# リファレンス) (NotInheritable) 修飾子付きで宣言されていません。 継承を意図していない型は、sealed 修飾子でマークし、基本型として使用できないようにします。 |
|
パブリック型または入れ子になったパブリック型で、静的なメンバーのみが宣言されています。また、パブリックまたはプロテクトの既定のコンストラクターが含まれます。 静的メンバーの呼び出しに型のインスタンスは必要ないため、コンストラクターは不要です。 安全性とセキュリティを確保するために、文字列引数を使用して文字列オーバーロードで URI オーバーロードを呼び出してください。 |
|
メソッドで URI の文字列形式を使用する場合、対応するオーバーロードを宣言し、URI クラスのインスタンスを使用します。こうすることで、安全な方法でこのサービスを実現できます。 |
|
この規則では、メソッドは URI (Uniform Resource Identifier) を返すと想定されます。 URI の文字列表現は解析エラーやエンコーディング エラーが発生しやすく、セキュリティ上の脆弱性の原因となる場合があります。 System.Uri クラスを使用すると、安全な方法でこのサービスを実現できます。 |
|
この規則では、プロパティは URI (Uniform Resource Identifier) を表すと想定されます。 URI の文字列表現は解析エラーやエンコーディング エラーが発生しやすく、セキュリティ上の脆弱性の原因となる場合があります。 System.Uri クラスを使用すると、安全な方法でこのサービスを実現できます。 |
|
文字列パラメーターが System.Uri パラメーターに置き換えられている点だけが異なるメソッド オーバーロードが型で宣言されています。 文字列パラメーターを使用するオーバーロードは、URI パラメーターを使用するオーバーロードを呼び出しません。 |
|
外部から参照可能な型では、特定の基本型が拡張されます。 別の型を使用してください。 |
|
具象型は、完全な実装を含む型であるため、インスタンス化できます。 このメンバーを広範囲に使用するには、具象型を推奨インターフェイスと置き換えます。 |
|
内部例外は、その内部スコープ内でのみ認識されます。 内部スコープの外側にある例外は、基本例外を使用しなければキャッチできません。 内部例外が T:System.Exception、T:System.SystemException、または T:System.ApplicationException を継承している場合、外部コードはその例外の処理に関する十分な情報を取得できません。 |
|
インスタンスのメソッドで、宣言型のインスタンス フィールドと名前が一致するパラメーターまたはローカル変数が宣言されていると、エラーの原因となります。 |
|
この規則は、線形独立のメソッド経路数を示す尺度で、条件分岐の数と複雑さによって決まります。 |
|
名前空間、型、メンバー、およびパラメーターの各識別子は、大文字/小文字以外のみでは区別できません。共通言語ランタイムを対象とする言語は、大文字と小文字を区別する必要はないためです。 |
|
名前空間の名前または型の名前が、プログラミング言語で、予約済みのキーワードと一致します。 名前空間と型の識別子は、共通言語ランタイムを対象にする言語で定義されているキーワードと一致しないようにします。 |
|
メソッドのシグネチャに、メソッドの本体で使用されていないパラメーターがあります。 |
|
使用されていないローカル変数や不要な引数があると、アセンブリのサイズが大きくなり、パフォーマンスが低下します。 |
|
パフォーマンス最適化の一般的な方法として、メモリではなくプロセッサのレジスタに値を格納する方法があります。これは "値のレジスタ格納" と呼ばれます。 すべてのローカル変数をレジスタ格納できるようにするには、ローカル変数の数を 64 個に制限します。 |
|
型で明示的な静的コンストラクターを宣言すると、Just-In-Time (JIT) コンパイラが、静的コンストラクターが呼び出されたことを確認するために、型の静的メソッドと静的インスタンス コンストラクターに個別にチェックを追加します。 静的コンストラクターのチェックによってパフォーマンスが低下することがあります。 |
|
プライベート メンバーまたは内部 (アセンブリ レベル) メンバーが、アセンブリ内において、また共通言語ランタイムおよびデリゲートのいずれからも呼び出されていません。 |
|
アセンブリ レベルの型のインスタンスが、アセンブリ内のコードから作成されません。 |
|
.NET Framework クラス ライブラリには、カスタム属性を取得するメソッドが用意されています。 既定では、これらのメソッドで属性の継承階層が検索されます。 属性をシールすると、継承階層の全体が検索されなくなるため、パフォーマンスが向上します。 |
|
ジャグ配列とは、その要素も配列である配列です。 要素を構成する配列のサイズは異なってもよいため、データ セットによっては無駄な空間が少なくなります。 |
|
値型の場合、Equals を継承した実装が Reflection ライブラリを使用して、すべてのフィールドの内容を比較します。 Reflection は計算コストが高いため、場合によってはすべてのフィールドで等値性を比較する必要はありません。 ユーザーがインスタンスの比較または並べ替えを行うことや、ハッシュ テーブル キーとしてインスタンスを使用することが予想される場合には、値型に Equals を実装する必要があります。 |
|
プロパティが読み取り専用であっても、プロパティで返される配列は書き込みから保護されません。 配列の改ざんを防ぐには、プロパティで配列のコピーを返す必要があります。 一般に、このようなプロパティを呼び出すときのパフォーマンス低下は理解されません。 |
|
String.Length プロパティまたは String.IsNullOrEmpty メソッドを使用して文字列を比較する方法は、Equals を使用する場合よりもはるかに高速です。 |
|
オブジェクトの有効期間を追跡する際にパフォーマンス オーバーヘッドが増大するため、ファイナライザーは可能な限り使用しないでください。 空のファイナライザーを使用すると、オーバーヘッドが増大するだけで何の利点もありません。 |
|
インスタンス データにアクセスしない、またはインスタンス メソッドを呼び出さないメンバーは、静的 (Visual Basic では共有) としてマークできます。 メソッドを静的としてマークすると、コンパイラはこれらのメンバーに対する非仮想呼び出しサイトを出力します。 パフォーマンス重視のコードでは、これにより大きくパフォーマンスを向上できます。 |
|
アセンブリ内でアクセスされていないと思われるプライベート フィールドが検出されました。 |
|
これにより、元のエラーの検出およびデバッグが困難になります。 |
|
プラットフォーム呼び出しメソッドが定義されましたが、同等の機能を持つメソッドが .NET Framework クラス ライブラリに存在します。 |
|
ArgumentException またはそのクラスから派生した例外の種類の既定 (パラメーターなし) のコンストラクターに対して呼び出しが行われたか、ArgumentException またはそのクラスから派生した例外の種類のパラメーター付きのコンストラクターに不適切な文字列型の引数が渡されました。 |
|
定数でも読み取り専用でもない静的フィールドは、スレッド セーフではありません。 このようなフィールドへのアクセスは、慎重に制御してください。また、クラス オブジェクトへのアクセスを同期するには、高度なプログラミング技術が必要です。 |
|
外部から参照できる列挙型が FlagsAttribute でマークされ、その列挙型に、2 の累乗でもなく、その列挙型で定義されている他の値の組み合わせでもない値が 1 つ以上含まれています。 |
|
finally 句または fault 句で例外が発生すると、アクティブな例外が新しい例外によって隠されます。 filter 句で例外が発生すると、ランタイムがその例外を暗黙的にキャッチします。 これにより、元のエラーの検出およびデバッグが困難になります。 |
|
ファイナライザーは、ファミリ アクセス修飾子を使用する必要があります。 |
|
継承メンバーのアクセス修飾子は変更しないでください。 継承メンバーをプライベートに変更しても、呼び出し元はメソッドの基本クラスの実装にアクセスできます。 |
|
共通言語ランタイムでは、戻り値の型以外は同じであるメンバーの区別に戻り値の型を使用することが許可されていますが、この機能は共通言語仕様ではなく、.NET プログラミング言語の共通機能でもありません。 |
|
パブリック型で等値演算子が実装されていますが、Object.Equals がオーバーライドされていません。 |
|
演算子のオーバーロードが検出され、予想される名前の代替メソッドが検出されませんでした。 名前付きの代替メンバーによって、演算子と同じ機能へアクセスできるようになります。また、演算子のオーバーロードをサポートしていない言語でプログラミングする場合でも、その代替メンバーを使用できます。 |
|
型で等値演算子または非等値演算子を実装し、逆の働きをする演算子を実装していません。 |
|
書き込み可能なコレクション プロパティにより、ユーザーはコレクションを異なるコレクションで置換できます。 読み取り専用プロパティは、コレクションを置換できないようにしますが、個別のメンバーが設定されることは回避できません。 |
|
パブリック型またはプロテクト型に、params キーワードではなく VarArgs 呼び出し規約を使用するパブリック メソッドまたはプロテクト メソッドが含まれています。 |
|
値型は、Object.Equals をオーバーライドしていますが、等値演算子を実装していません。 |
|
"uri"、"URI"、"urn"、"URN"、"url"、または "URL" という名前を持つ文字列パラメーターが指定されているメソッドに対して、呼び出しが行われました。 そのメソッドの型宣言に対応するメソッドのオーバーロードが存在し、それに対して System.Uri パラメーターが指定されています。 |
|
型に System.Runtime.Serialization.OptionalFieldAttribute 属性でマークされているフィールドがあり、その型に逆シリアル化のイベント処理メソッドがありません。 |