Desde que me lembro, evitei usar a instrução switch fall-through. Na verdade, não consigo me lembrar de alguma vez ter entrado em minha consciência como uma forma possível de fazer as coisas, já que foi perfurado em minha cabeça logo no início que não era nada mais do que um bug na instrução switch. No entanto, hoje encontrei um código que o usa por design, o que me fez imediatamente imaginar o que todos na comunidade pensam sobre o erro de instrução switch.
É algo que uma linguagem de programação não deveria permitir explicitamente (como o C #, embora forneça uma solução alternativa) ou é um recurso de qualquer linguagem poderoso o suficiente para deixar nas mãos do programador?
Edit: Eu não fui específico o suficiente para o que quero dizer com falha. Eu uso muito esse tipo:
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something
break;
case 2:
case 3:
case 4:
// Do something
break;
}
No entanto, estou preocupado com algo assim.
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something, but fall through to the other cases
// after doing it.
case 2:
case 3:
case 4:
// Do something else.
break;
}
Dessa forma, sempre que o caso for 0, 1, ele fará tudo na instrução switch. Eu vi isso por design e só não sei se concordo que as instruções switch devem ser usadas dessa forma. Acho que o primeiro exemplo de código é muito útil e seguro. O segundo parece meio perigoso.
fonte
Respostas:
Pode depender do que você considera um avanço. Eu estou bem com esse tipo de coisa:
Mas se você tiver um rótulo de caso seguido por um código que passa por outro rótulo de caso, eu sempre consideraria isso mal. Talvez mover o código comum para uma função e chamar de ambos os lugares seja uma ideia melhor.
E, por favor, note que eu uso a definição C ++ FAQ de "mal"
fonte
É uma espada de dois gumes. Às vezes é muito útil, mas frequentemente perigoso.
Quando fica bom? Quando você quiser que 10 casos sejam processados da mesma maneira ...
A única regra de que gosto é que, se você fizer algo extravagante e excluir o intervalo, precisará de um comentário claro / * FALLTHROUGH * / para indicar que essa foi sua intenção.
fonte
if(condition > 1 && condition <10) {condition = 1}; switch(...
salvar casos (para uma aparência clara) e todos podem ver que você realmente deseja que esses casos desencadeiem a mesma ação.Você já ouviu falar do dispositivo de Duff ? Este é um ótimo exemplo de como usar switch fallthrough.
É um recurso que pode ser usado e pode ser abusado, como quase todos os recursos de linguagem.
fonte
O fall-through é realmente uma coisa útil, dependendo do que você está fazendo. Considere esta maneira simples e compreensível de organizar as opções:
Imagine fazer isso com if / else. Seria uma bagunça.
fonte
Pode ser muito útil algumas vezes, mas, em geral, nenhum erro é o comportamento desejado. O fall-through deve ser permitido, mas não implícito.
Um exemplo, para atualizar versões antigas de alguns dados:
fonte
Adoraria uma sintaxe diferente para substitutos em switches, algo como, errr ..
Nota: Isso já seria possível com enums, se você declarar todos os casos em seu enum usando sinalizadores, certo? Também não parece tão ruim; os casos poderiam (deveriam?) muito bem já fazer parte do seu enum.
Talvez este seja um bom caso (sem trocadilhos) para uma interface fluente usando métodos de extensão? Algo como, errr ...
Embora seja provavelmente ainda menos legível: P
fonte
Como com qualquer coisa: se usado com cuidado, pode ser uma ferramenta elegante.
Porém, acho que as desvantagens mais do que justificam não usá-lo, e finalmente não permitir mais (C #). Entre os problemas estão:
Bom uso de um switch / case fall-through:
Baaaaad uso de um switch / case fall-through:
Isso pode ser reescrito usando construções if / else sem nenhuma perda em minha opinião.
Minha palavra final: fique longe de rótulos de caso que falham como no exemplo ruim , a menos que você esteja mantendo um código legado onde esse estilo é usado e bem compreendido.
fonte
É poderoso e perigoso. O maior problema com o fall-through é que não é explícito. Por exemplo, se você encontrar um código editado com frequência que tem um switch com falhas, como saber se isso é intencional e não um bug?
Onde quer que eu o use, asseguro-me de que esteja devidamente comentado:
fonte
Usar a falha como no seu primeiro exemplo é claramente OK, e eu não consideraria uma falha real.
O segundo exemplo é perigoso e (se não for comentado extensivamente) não óbvio. Eu ensino meus alunos a não usarem tais construções, a menos que considerem que vale a pena dedicar um bloco de comentários a elas, que descreve que se trata de uma falha intencional e por que essa solução é melhor do que as alternativas. Isso desencoraja o uso descuidado, mas ainda o torna permitido nos casos em que é usado com vantagem.
Isso é mais ou menos equivalente ao que fizemos em projetos espaciais quando alguém quis violar o padrão de codificação: eles tiveram que solicitar dispensa (e fui chamado para aconselhar sobre a decisão).
fonte
Não gosto que minhas
switch
declarações falhem - são muito propensas a erros e difíceis de ler. A única exceção é quando váriascase
instruções fazem exatamente a mesma coisa.Se houver algum código comum que várias ramificações de uma instrução switch desejam usar, eu extraio isso em uma função comum separada que pode ser chamada em qualquer ramificação.
fonte
Em alguns casos, usar falhas é um ato de preguiça por parte do programador - eles poderiam usar uma série de || instruções, por exemplo, mas em vez disso, use uma série de casos de switch 'pega-tudo'.
Dito isso, descobri que eles são especialmente úteis quando sei que eventualmente , vou precisar das opções de qualquer maneira (por exemplo, em uma resposta do menu), mas ainda não implementei todas as opções. Da mesma forma, se você estiver fazendo um fall-through para 'a' e 'A', acho substancialmente mais limpo usar o fall-through do switch do que uma instrução if composta.
Provavelmente é uma questão de estilo e de como os programadores pensam, mas geralmente não gosto de remover componentes de uma linguagem em nome de 'segurança' - é por isso que tento mais para C e suas variantes / descendentes do que, digamos, Java. Gosto de ser capaz de ficar brincando com dicas e coisas do gênero, mesmo quando não tenho "razão" para isso.
fonte
O fall-through deve ser usado apenas quando é usado como uma tabela de salto para um bloco de código. Se houver alguma parte do código com uma quebra incondicional antes de mais casos, todos os grupos de casos devem terminar dessa forma.
Qualquer outra coisa é "mal".
fonte