CA1008:Enums は 0 値を含んでいなければなりません

プロパティ
ルール ID CA1008
Title Enums は 0 値を含んでいなければなりません
[カテゴリ] デザイン
修正が中断ありか中断なしか 中断なし - フラグ以外の列挙型に None 値を追加するように求めるメッセージが表示された場合。 中断あり - 列挙型の値の名前変更または削除を求めるメッセージが表示された場合。
.NET 8 では既定で有効 いいえ

原因

System.FlagsAttribute が適用されていない列挙型では、値が 0 であるメンバーは定義されません。 または、FlagsAttribute が適用されている列挙型では、値は 0 であるが、その名前は 'None' ではないメンバーが定義されます。 または、列挙型では、0 値のメンバーが複数定義されます。

既定では、この規則の対象は外部から参照できる列挙型のみですが、これは構成可能です。

規則の説明

初期化されていない列挙型の既定値は、他の値型と同様に 0 です。 非フラグ属性付きの列挙型では、値が 0 であるメンバーを定義する必要があります。これは、既定値を有効な列挙型の値にするためです。 必要に応じて、メンバーの名前を 'None' (または許可されている追加の名前のいずれか) にします。 それ以外の場合は、最も頻繁に使用されるメンバーに 0 を割り当てます。 既定では、最初の列挙型メンバーの値が宣言内に設定されていない場合、その値は 0 になります。

FlagsAttribute を適用した列挙型で 0 値のメンバーを定義する場合は、その名前を "None" (あるいは、許可されている追加の名前のいずれか) にして、列挙型に設定済みの値がないことを示す必要があります。 他の目的で 0 値のメンバーを使用することは、FlagsAttribute および AND のビット単位の演算子がメンバーに対して役に立たないという点で、OR の使用に反しています。 これは 1 つのメンバーにのみ値 0 を割り当てる必要があることを意味します。 値が 0 である複数のメンバーがフラグ属性付きの列挙型で検出された場合、Enum.ToString() からは、0 でないメンバーに対して正しくない結果が返されます。

違反の修正方法

非フラグ属性付き列挙型について、この規則違反を修正するには、値が 0 であるメンバーを定義します。これは非破壊的変更です。 0 値のメンバーを定義するフラグ属性付き列挙型の場合、このメンバーに "None" という名前を付け、値が 0 の他のメンバーをすべて削除します。これは破壊的変更です。

どのようなときに警告を抑制するか

以前に出荷されたフラグ属性付きの列挙型の場合を除き、この規則からの警告を抑制しないでください。

警告を抑制する

単一の違反を抑制するだけの場合は、ソース ファイルにプリプロセッサ ディレクティブを追加して無効にしてから、規則をもう一度有効にします。

#pragma warning disable CA1008
// The code that's violating the rule is on this line.
#pragma warning restore CA1008

ファイル、フォルダー、またはプロジェクトの規則を無効にするには、構成ファイルでその重要度を none に設定します。

[*.{cs,vb}]
dotnet_diagnostic.CA1008.severity = none

詳細については、「コード分析の警告を抑制する方法」を参照してください。

分析するコードを構成する

次のオプションを使用して、コードベースのどの部分に対してこの規則を実行するか構成します。

このオプションを構成できる対象は、この規則だけ、それを適用するすべての規則、それを適用するこのカテゴリ (デザイン) のすべての規則のいずれかです。 詳細については、「コード品質規則の構成オプション」を参照してください。

特定の API サーフェイスを含める

ユーザー補助に基づいて、この規則を実行するコードベースの部分を構成できます。 たとえば、非パブリック API サーフェイスでのみ規則を実行するように指定するには、プロジェクトの .editorconfig ファイルに次のキーと値のペアを追加します。

dotnet_code_quality.CAXXXX.api_surface = private, internal

追加のゼロ値フィールド名

.NET 7 以降のバージョンでは、None 以外で 0 値列挙フィールドに許可されるその他の名前を構成します。 複数の名前は | 文字で区切ります。 次の表に例を示します。

オプション値 まとめ
dotnet_code_quality.CA1008.additional_enum_none_names = Never NoneNever の両方を許可します
dotnet_code_quality.CA1008.additional_enum_none_names = Never|Nothing NoneNeverNothing を許可します

次の例では、規則に適合する 2 つの列挙型と、規則に違反する列挙型 BadTraceOptions を示します。

using System;

namespace ca1008
{
    public enum TraceLevel
    {
        Off = 0,
        Error = 1,
        Warning = 2,
        Info = 3,
        Verbose = 4
    }

    [Flags]
    public enum TraceOptions
    {
        None = 0,
        CallStack = 0x01,
        LogicalStack = 0x02,
        DateTime = 0x04,
        Timestamp = 0x08,
    }

    [Flags]
    public enum BadTraceOptions
    {
        CallStack = 0,
        LogicalStack = 0x01,
        DateTime = 0x02,
        Timestamp = 0x04,
    }

    class UseBadTraceOptions
    {
        static void MainTrace()
        {
            // Set the flags.
            BadTraceOptions badOptions =
               BadTraceOptions.LogicalStack | BadTraceOptions.Timestamp;

            // Check whether CallStack is set.
            if ((badOptions & BadTraceOptions.CallStack) ==
                BadTraceOptions.CallStack)
            {
                // This 'if' statement is always true.
            }
        }
    }
}
Imports System

Namespace ca1008

    Public Enum TraceLevel
        Off = 0
        AnError = 1
        Warning = 2
        Info = 3
        Verbose = 4
    End Enum

    <Flags>
    Public Enum TraceOptions
        None = 0
        CallStack = &H1
        LogicalStack = &H2
        DateTime = &H4
        Timestamp = &H8
    End Enum

    <Flags>
    Public Enum BadTraceOptions
        CallStack = 0
        LogicalStack = &H1
        DateTime = &H2
        Timestamp = &H4
    End Enum

    Class UseBadTraceOptions

        Shared Sub Main1008()

            ' Set the flags.
            Dim badOptions As BadTraceOptions =
            BadTraceOptions.LogicalStack Or BadTraceOptions.Timestamp

            ' Check whether CallStack is set.
            If ((badOptions And BadTraceOptions.CallStack) =
             BadTraceOptions.CallStack) Then
                ' This 'If' statement is always true.
            End If

        End Sub

    End Class

End Namespace

関連項目