Se eu estiver usando uma instrução switch para manipular valores de uma enumeração (pertencente à minha classe) e tiver um caso para cada valor possível - vale a pena adicionar código para manipular o caso "padrão"?
enum MyEnum
{
MyFoo,
MyBar,
MyBat
}
MyEnum myEnum = GetMyEnum();
switch (myEnum)
{
case MyFoo:
DoFoo();
break;
case MyBar:
DoBar();
break;
case MyBat:
DoBat();
break;
default:
Log("Unexpected value");
throw new ArgumentException()
}
Eu não acho que é porque esse código nunca pode ser alcançado (mesmo com testes de unidade). Meu colega de trabalho discorda e acha que isso nos protege contra comportamentos inesperados causados por novos valores sendo adicionados ao MyEnum.
O que você diz, comunidade?
MyEnum
depois passar pelo seu switch?switch
completamente a instrução.Respostas:
A inclusão do caso padrão não altera a maneira como seu código funciona, mas torna seu código mais sustentável. Ao fazer a quebra de código de uma maneira óbvia (registre uma mensagem e lance uma exceção), você inclui uma grande seta vermelha para o estagiário que sua empresa contrata no próximo verão para adicionar alguns recursos. A seta diz: "Ei, você! Sim, estou falando com VOCÊ! Se você quiser adicionar outro valor à enum, é melhor adicionar um caso aqui também". Esse esforço extra pode adicionar alguns bytes ao programa compilado, o que é algo a considerar. Mas também salvará alguém (talvez até o futuro você) em algum momento entre uma hora e um dia de coçar a cabeça improdutivo.
Atualização: A situação descrita acima, ou seja, proteger contra valores adicionados a uma enumeração posteriormente, também pode ser detectada pelo compilador. Clang (e gcc, eu acho) por padrão emitirá um aviso se você ativar um tipo enumerado, mas não tiver um caso que cubra todos os valores possíveis na enumeração. Portanto, por exemplo, se você remover o
default
caso do seu comutador e adicionar um novo valorMyBaz
à enumeração, receberá um aviso dizendo:Deixar o compilador detectar casos não descobertos é que elimina amplamente a necessidade daquele
default
caso inacessível que inspirou sua pergunta em primeiro lugar.fonte
Eu também estava conversando com um colega sobre isso hoje de manhã - é realmente lamentável, mas acho que lidar com o padrão é necessário por segurança, por dois motivos:
Primeiro, como seu colega de trabalho menciona, ele prova o código contra novos valores sendo adicionados à enumeração. Isso pode ou não parecer uma possibilidade, mas está sempre lá.
Mais importante, dependendo do idioma / compilador, pode ser possível ter valores que não são membros da enumeração na sua variável comutada. Por exemplo, em C #:
Ao adicionar o simples
case default:
e lançar uma exceção, você se protegeu contra esse caso estranho em que "nada" acontece, mas "algo" deveria ter acontecido.Infelizmente, basicamente, sempre que eu escrevo mais uma instrução switch, é porque estou verificando os casos de uma enumeração. Eu realmente gostaria que o comportamento "jogar por padrão" pudesse ser imposto pelo próprio idioma (pelo menos adicionando uma palavra-chave).
fonte
Adicionar um caso padrão, mesmo que você nunca espere alcançá-lo, pode ser uma coisa boa. Isso tornará a depuração muito mais fácil se o seu código lançar uma exceção "Isso não deveria ter acontecido" imediatamente, ou mais tarde no programa, lançando alguma exceção misteriosa ou retornando resultados inesperados sem erros.
fonte
Eu digo:
Tente adicionar outro tipo para
MyEnum
. Então mude esta linha:para
Em seguida, execute seu código com o caso padrão e sem o caso padrão. Qual comportamento você prefere?
Ter o caso padrão também pode ser útil para capturar
NULL
valores e impedirNullPointerExceptions
.fonte
Se você tivesse alguma idéia de como economizar tempo de máquina insistindo no caso padrão, não precisaria fazer a pergunta. Não fazer nada silenciosamente em uma condição de erro - você captura silenciosamente exceções que nunca deveriam acontecer? Deixando "minas" para programadores que o seguem, da mesma forma inaceitável.
Se o seu código nunca for alterado ou modificado e estiver 100% livre de erros, deixar de fora o caso padrão pode estar OK.
Ada (o avô de linguagens de programação robustas) não compila uma opção em uma enumeração, a menos que todas as enumerações sejam cobertas ou haja um manipulador padrão - esse recurso está na minha lista de desejos para todas as linguagens. Nosso padrão de codificação Ada afirma que, com opções ativadas, o tratamento explícito de todos os valores, sem padrão, é a maneira preferida de lidar com essa situação.
fonte