列挙型デザインEnum Design

列挙型は、特別な種類の値型です。Enums are a special kind of value type. 列挙型には、単純な列挙型とフラグ列挙型の2種類があります。There are two kinds of enums: simple enums and flag enums.

単純な列挙型は、選択の小さな閉じられたセットを表します。Simple enums represent small closed sets of choices. 単純な列挙型の一般的な例としては、一連の色があります。A common example of the simple enum is a set of colors.

フラグ列挙型は、列挙値のビットごとの演算をサポートするように設計されています。Flag enums are designed to support bitwise operations on the enum values. Flags 列挙型の一般的な例として、オプションの一覧があります。A common example of the flags enum is a list of options.

厳密に型指定されたパラメーター、プロパティ、および値のセットを表す戻り値には、列挙型を使用✔️ます。✔️ DO use an enum to strongly type parameters, properties, and return values that represent sets of values.

✔️は、静的な定数ではなく列挙型を使用するようにします。✔️ DO favor using an enum instead of static constants.

❌ オープンセットには列挙型を使用しないでください (オペレーティングシステムのバージョン、友人の名前など)。❌ DO NOT use an enum for open sets (such as the operating system version, names of your friends, etc.).

❌ 将来使用するための予約済み列挙値を指定しないでください。❌ DO NOT provide reserved enum values that are intended for future use.

後の段階で、既存の列挙に値をいつでも追加できます。You can always simply add values to the existing enum at a later stage. 列挙型に値を追加する方法の詳細については、「 列挙型への値の追加 」を参照してください。See Adding Values to Enums for more details on adding values to enums. 予約済みの値は、実際の値のセットを汚染するだけで、ユーザーエラーにつながる傾向があります。Reserved values just pollute the set of real values and tend to lead to user errors.

❌ 1つの値のみを使用して enum を公開しないようにします。❌ AVOID publicly exposing enums with only one value.

C Api の将来の拡張性を確保するための一般的な方法は、メソッドシグネチャに予約済みのパラメーターを追加することです。A common practice for ensuring future extensibility of C APIs is to add reserved parameters to method signatures. このような予約済みのパラメーターは、単一の既定値を持つ列挙型として表すことができます。Such reserved parameters can be expressed as enums with a single default value. これは、マネージ Api では実行できません。This should not be done in managed APIs. メソッドのオーバーロードでは、将来のリリースでパラメーターを追加できます。Method overloading allows adding parameters in future releases.

❌ 列挙型には、sentinel 値を含めないでください。❌ DO NOT include sentinel values in enums.

Framework 開発者にとっては便利な場合もありますが、sentinel 値はフレームワークのユーザーにとって混乱を招くことがあります。Although they are sometimes helpful to framework developers, sentinel values are confusing to users of the framework. 列挙型によって表されるセットの値の1つではなく、列挙型の状態を追跡するために使用されます。They are used to track the state of the enum rather than being one of the values from the set represented by the enum.

単純な列挙型で値0を指定する✔️ます。✔️ DO provide a value of zero on simple enums.

"None" のような値を呼び出すことを検討してください。Consider calling the value something like "None." このような値がこの特定の列挙型に適していない場合は、列挙型の最も一般的な既定値に0の基になる値を代入する必要があります。If such a value is not appropriate for this particular enum, the most common default value for the enum should be assigned the underlying value of zero.

Int32次のいずれかに該当しない場合は、列挙型の基になる型として (ほとんどのプログラミング言語で既定) を使用することを✔️してください。✔️ CONSIDER using Int32 (the default in most programming languages) as the underlying type of an enum unless any of the following is true:

  • 列挙型はフラグの列挙型であり、32を超えるフラグがあるか、または今後さらに多くなることが予想されます。The enum is a flags enum and you have more than 32 flags, or expect to have more in the future.

  • Int32異なるサイズの列挙型が必要なアンマネージコードとの相互運用性を容易にするために、基になる型はとは異なる必要があります。The underlying type needs to be different than Int32 for easier interoperability with unmanaged code expecting different-size enums.

  • 基になる型が小さいと、スペースが大幅に節約されます。A smaller underlying type would result in substantial savings in space. 列挙型が主に制御フローの引数として使用されることが予想される場合、サイズの違いはほとんどありません。If you expect the enum to be used mainly as an argument for flow of control, the size makes little difference. 次の場合、サイズを節約することが重要になります。The size savings might be significant if:

    • 非常に頻繁にインスタンス化される構造体またはクラスのフィールドとして列挙型を使用することを想定しています。You expect the enum to be used as a field in a very frequently instantiated structure or class.

    • ユーザーは、大規模な配列または列挙型インスタンスのコレクションを作成することを想定しています。You expect users to create large arrays or collections of the enum instances.

    • 列挙型の多数のインスタンスをシリアル化することを想定しています。You expect a large number of instances of the enum to be serialized.

メモリ内での使用については、マネージオブジェクトが常に固定されていることに注意してください。したがって、インスタンス DWORD 全体のサイズは常にに切り上げられるため、より小さな列挙型をパックするために、インスタンス内に複数の列挙型またはその他の小さな構造体を効果的に使用する必要があり DWORD ます。For in-memory usage, be aware that managed objects are always DWORD-aligned, so you effectively need multiple enums or other small structures in an instance to pack a smaller enum with in order to make a difference, because the total instance size is always going to be rounded up to a DWORD.

✔️は、複数形の名詞または名詞句を持つ列挙型と、単数形または名詞句を持つ単純な列挙型を使用します。✔️ DO name flag enums with plural nouns or noun phrases and simple enums with singular nouns or noun phrases.

❌ を直接拡張しないで System.Enum ください。❌ DO NOT extend System.Enum directly.

System.Enum は、ユーザー定義の列挙を作成するために CLR によって使用される特殊な型です。System.Enum is a special type used by the CLR to create user-defined enumerations. ほとんどのプログラミング言語には、この機能にアクセスできるプログラミング要素が用意されています。Most programming languages provide a programming element that gives you access to this functionality. たとえば、C# では、 enum キーワードを使用して列挙型を定義します。For example, in C# the enum keyword is used to define an enumeration.

フラグ列挙型のデザインDesigning Flag Enums

✔️には、 System.FlagsAttribute 列挙型にフラグを適用します。✔️ DO apply the System.FlagsAttribute to flag enums. 単純な列挙型にはこの属性を適用しないでください。Do not apply this attribute to simple enums.

フラグの列挙値には2の累乗を使用して、ビットごとの OR 演算を使用して自由に組み合わせることができるように✔️ます。✔️ DO use powers of two for the flag enum values so they can be freely combined using the bitwise OR operation.

一般的に使用されるフラグの組み合わせに対して特別な列挙値を指定することを✔️検討します。✔️ CONSIDER providing special enum values for commonly used combinations of flags.

ビットごとの演算は高度な概念であり、単純なタスクには必要ありません。Bitwise operations are an advanced concept and should not be required for simple tasks. ReadWrite このような特殊な値の例を次に示します。ReadWrite is an example of such a special value.

❌ 値の特定の組み合わせが無効な場合は、フラグの列挙型を作成しないようにします。❌ AVOID creating flag enums where certain combinations of values are invalid.

❌ 次のガイドラインで規定されているように、値が "すべてのフラグがクリアされています" を表し、適切な名前が付けられている場合を除き、フラグの列挙値0を使用しないでください。❌ AVOID using flag enum values of zero unless the value represents "all flags are cleared" and is named appropriately, as prescribed by the next guideline.

✔️には、フラグの列挙型の0の値を指定 None します。✔️ DO name the zero value of flag enums None. フラグの列挙型の場合、値は常に "すべてのフラグがクリアされている" ことを意味します。For a flag enum, the value must always mean "all flags are cleared."

列挙型への値の追加Adding Value to Enums

列挙型に値を追加する必要があることを既に確認しています。It is very common to discover that you need to add values to an enum after you have already shipped it. 新しく追加された値が既存の API から返された場合、アプリケーションの互換性の問題が発生する可能性があります。これは、正しく記述されていないアプリケーションが新しい値を正しく処理できない可能性があるためです。There is a potential application compatibility problem when the newly added value is returned from an existing API, because poorly written applications might not handle the new value correctly.

互換性のリスクが小さいとしても、列挙値に値を追加することを検討✔️。✔️ CONSIDER adding values to enums, despite a small compatibility risk.

列挙型への追加によって発生するアプリケーションの非互換性に関する実際のデータがある場合は、新しい値と古い値を返す新しい API を追加し、古い API を廃止することを検討してください。これにより、古い値だけが返されます。If you have real data about application incompatibilities caused by additions to an enum, consider adding a new API that returns the new and old values, and deprecate the old API, which should continue returning just the old values. これにより、既存のアプリケーションに互換性があることが保証されます。This will ensure that your existing applications remain compatible.

©2005、2009 Microsoft Corporation の部分。すべての権限が予約されています。Portions © 2005, 2009 Microsoft Corporation. All rights reserved.

2008 年 10 月 22 日に Microsoft Windows Development シリーズの一部として、Addison-Wesley Professional によって発行された、Krzysztof Cwalina および Brad Abrams による「Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition」 (フレームワーク デザイン ガイドライン: 再利用可能な .NET ライブラリの規則、用法、パターン、第 2 版) から Pearson Education, Inc. の許可を得て再印刷されています。Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, published Oct 22, 2008 by Addison-Wesley Professional as part of the Microsoft Windows Development Series.

関連項目See also