9

列挙型に初期化されていない値を含める必要があるかどうかについて議論していました。例えば。我々は持っています

public enum TimeOfDayType
{
   Morning
   Afternoon
   Evening
}

また

public enum TimeOfDayType
{
   None
   Morning
   Afternoon
   Evening
}

何もないはずではないと思いますが、初期化時に有効な値にデフォルト設定する必要があります。しかし、他の人は、None または NotSet である別の列挙型を持つことによって、ユニット化された状態の兆候があるべきだと考えました。

考え?

4

6 に答える 6

13

null 許容型について言えば、列挙型の初期化を強制する/強制しないという問題を解決するために使用できると思います。私たちが持っていると言う

enum Color { Red, Blue }

そして、あなたが関数を持っているとしましょう:

void Draw(Color c);

その関数は有効なColor. ただし、次の関数を使用することもできます。

void Draw(Color? c);

これは、関数が色を渡されなくても処理できることを示しています ( null「ドントケア」を示すために渡されます)。

まあ、それはNoneメンバーの1つの代替手段です。

于 2008-12-06T02:33:36.247 に答える
7

私は常に列挙型リテラルの1つをゼロに設定します。このリテラルは、常に「None」または「NotSet」という名前である必要はありません。デフォルトとして非常にうまく機能するリテラルがあるかどうかによって異なります。

列挙型(null許容の列挙型を除く)は常にメモリ内のCLRによってゼロに初期化されるため、1をゼロに設定しました。また、リテラルの1つを定義しない場合、このメモリーには不正な値が含まれています。また、列挙型をフラグとして使用する場合。デフォルト値を使用してビット単位の比較を行うことはできません。結果は常にゼロになります。

FxCopを有効にすると、リテラルがデフォルトとして定義されているかどうかがチェックされます。彼らがそのためのルールを持っているとき、それは「良い習慣」であるように思われます。

于 2008-12-06T08:32:39.593 に答える
5

以前の回答のいくつかでは、解決策として nullable enum が提案されました。ただし、null 許容列挙型には、クライアントが列挙型を使用するたびに null 値をチェックするという欠点があります。逆に、デフォルト値が「None」の場合は、意味のある値にスイッチを使用して「None」を無視するオプションがあり、enum 変数が null になる可能性があることを心配する必要はありません。

とにかく、デフォルト値を「なし」にするか、列挙型をnull可能にすることは、列挙型が一部のクラスのデフォルトコンストラクターで引数として使用される場合にのみ意味があると思います。そして、自問する必要があります。そのクラスのオブジェクトには、意味のあるデフォルト値があるべきではありませんか? あなたの例を TimeOfDayType 列挙型で使用する - オブジェクトを TimeOfDayType.None で初期化する場合、値を朝、午後、または夕方に変更する前にそれを使用することはできません。デフォルトが「なし」ではなく「モーニング」であるとは言えませんか? または - どちらがより良い - オブジェクトが必要とする列挙値を既に知っていれば、オブジェクトを作成できませんでしたか? 初期の設計段階で問題に正しく取り組めば、列挙型に特別なデフォルト値をまったく必要としないはずです。

もちろん、上記はすべて一般化したものです。あなたの特定のシナリオには当てはまらないかもしれません。そのため、詳細を教えていただければ、問題についてより徹底的に話し合うことができます。

于 2008-12-06T04:00:46.490 に答える
5

「デフォルト」メンバーがない場合、リテラル int 0 を表す値を持つことは価値があると思います。

何があっても、指定された列挙型はリテラル値 0 で作成されます。ここでの最も単純なケースは、構造体のメンバーとしてです。AC# 構造体には常に、すべてのフィールドをデフォルト値に初期化する空のデフォルト コンストラクターがあります。列挙型の場合、それはリテラル値 0 になります。問題は、それをどのように処理するかです。

私にとって、これはスタイルの問題です。列挙型が値に明示的に初期化されていない場合、任意の有効な値または明示的な初期化の欠如を示す特定の値を指定する必要がありますか?

enum Color { Unknown, Red, Blue }
enum Color2 { Red,Blue }
struct Example<T> {
  Color color;
}

static void SomeMethod() {
  var v1 = new Example<Color>();
  var v2 = new Example<Color2>();
}

v1 の場合、カラー フィールドが検査されると、初期化されていないフィールドとして明示的にラベル付けされます。v2 では、フィールドは単純に「赤」になります。プログラマーが明示的に「赤」に設定されているか、暗黙のデフォルト値が「赤」に設定されているかを検出する方法はありません。

これが問題を引き起こす別のケースは、列挙値に対して switch ステートメントを実行することです。Color2 の定義を少し変更してみましょう。

enum Color2 { Red = 1, Blue = 2 }
static void SomeOtherMethod(p1 as Example<Color2>) {
  switch ( p1.color ) {
   case Color.Red: {} 
   case Color.Blue: {}
   default: {throw new Exception("What happened?"); }
  }
}

スイッチは、列挙型のすべての明示的な値を処理します。ただし、このコードは Example<Color2> の既定のコンストラクターでは失敗し、このコンストラクターを抑制する方法はありません。

これにより、もう少し重要なルールが生まれます: リテラル値 0 に対して明示的な列挙値を使用します。

于 2008-12-06T04:01:20.250 に答える
3

フランクの答えに追加するだけで、列挙型でnullableよりも「なし」の項目を選択するのは、列挙型がフラグとして使用されているときだけです。「なし」アイテムの ID は 0 です。

于 2008-12-06T02:54:26.763 に答える
1

タイプによって使い方が異なります。多くの場合、このタイプのユーザーは「未定義」の値を持たない方が簡単です。これは、1 つの値を特殊なケースにする必要がないためです。ただし、必要な場合は (値が列挙された値のいずれでもない状態である必要がある場合があるため)、1 つ必要です。通常、1 つではなく 2 つの列挙型を使用して特殊なケースのコードを保存することはありません。

これは、null 許容型を使用する必要があるかどうかを尋ねるようなものです。

于 2008-12-06T02:14:17.860 に答える