CA1008: Enumerações devem ter valor zero

Property Valor
ID da regra CA1008
Título Enumerações devem ter valor zero
Categoria Projetar
A correção é interruptiva ou sem interrupção Sem interrupção – quando você é solicitado a adicionar um valor None a uma enumeração não sinalizadora. Interruptiva – quando você é solicitado a renomear ou remover algum valor de enumeração.
Habilitado por padrão no .NET 8 Não

Causa

Uma enumeração sem um System.FlagsAttribute aplicado não define um membro que tenha um valor zero. Ou então, uma enumeração que tem um FlagsAttribute aplicado define um membro que tem um valor zero, mas seu nome não é 'Nenhum'. Ou, ainda, a enumeração define vários membros com valor zero.

Por padrão, essa regra apenas analisa as enumerações visíveis externamente, mas isso é configurável.

Descrição da regra

O valor padrão de uma enumeração não inicializada, assim como o de outros tipos de valor, é zero. Uma enumeração não atribuída a sinalizadores deve definir um membro usando o valor de zero de forma que o valor padrão seja um valor válido da enumeração. Se apropriado, nomeie o membro como 'Nenhum' (ou um dos nomes permitidos adicionais). Caso contrário, atribua zero ao membro de uso mais frequente. Por padrão, se o valor do primeiro membro de enumeração não estiver definido na declaração, seu valor será zero.

Se uma enumeração que tem o atributo FlagsAttribute aplicado definir um membro com valor zero, seu nome deverá ser “None” (ou um dos nomes permitidos adicionais) para indicar que nenhum valor foi definido na enumeração. O uso de um membro com valor zero para qualquer outra finalidade é contrário ao uso do FlagsAttribute em que os operadores bit a bit AND e OR são sem utilidade com o membro. Isso implica que apenas um membro deva ter o valor zero atribuído. Se vários membros que têm o valor zero ocorrerem em uma enumeração atribuída a sinalizadores, Enum.ToString() retornará resultados incorretos para membros que não são zero.

Como corrigir violações

Para corrigir uma violação dessa regra para enumerações não sinalizadoras, defina um membro que tenha o valor zero; essa é uma alteração sem interrupção. Para enumerações atribuídas a sinalizadores que definem um membro com valor zero, nomeie este membro como 'Nenhum' e exclua qualquer outro membro que tenha um valor zero; essa é uma alteração interruptiva.

Quando suprimir avisos

Não suprima um aviso dessa regra, exceto para enumerações atribuídas a sinalizadores que foram enviadas anteriormente.

Suprimir um aviso

Para suprimir apenas uma violação, adicione diretivas de pré-processador ao arquivo de origem a fim de desabilitar e, em seguida, reabilitar a regra.

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

Para desabilitar a regra em um arquivo, uma pasta ou um projeto, defina a severidade como none no arquivo de configuração.

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

Para obter mais informações, confira Como suprimir avisos de análise de código.

Configurar código para analisar

Use a opção a seguir para configurar em quais partes da base de código essa regra deve ser executada.

Você pode configurar essa opção apenas para essa regra, para todas as regras às quais ela se aplica ou para todas as regras nessa categoria (Design) às quais ela se aplica. Para saber mais, confira Opções de configuração de regra de qualidade de código.

Incluir superfícies de API específicas

É possível configurar em quais partes da base de código essa regra deverá ser executada, com base na acessibilidade. Por exemplo, para especificar que a regra deverá ser executada apenas na superfície de API não pública, adicione o seguinte par chave-valor a um arquivo .editorconfig no projeto:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Nomes de campo de valor zero adicionais

No .NET 7 e versões posteriores, você pode configurar outros nomes permitidos para um campo de enumeração de valor zero, além de None. Separe vários nomes pelo caractere |. A tabela a seguir mostra alguns exemplos.

Valor de opção Resumo
dotnet_code_quality.CA1008.additional_enum_none_names = Never Permite None e Never
dotnet_code_quality.CA1008.additional_enum_none_names = Never|Nothing Permite None, Never eNothing

Exemplo

O exemplo a seguir mostra duas enumerações que satisfazem a regra e uma enumeração, BadTraceOptions, que viola a regra.

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

Confira também