D'aussi loin que je me souvienne, j'ai évité d'utiliser une instruction switch fall-through. En fait, je ne me souviens pas que cela soit entré dans ma conscience comme un moyen possible de faire les choses car il m'a été percé très tôt dans la tête que ce n'était rien de plus qu'un bug dans la déclaration de commutation. Cependant, aujourd'hui, j'ai rencontré du code qui l'utilise par conception, ce qui m'a immédiatement amené à me demander ce que tout le monde dans la communauté pense de l'échec des instructions switch.
Est-ce quelque chose qu'un langage de programmation ne devrait explicitement pas autoriser (comme le fait C #, bien qu'il fournisse une solution de contournement) ou est-ce une fonctionnalité de tout langage suffisamment puissant pour être laissé entre les mains du programmeur?
Edit: Je n'étais pas assez précis sur ce que j'entendais par fall-through. J'utilise beaucoup ce type:
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something
break;
case 2:
case 3:
case 4:
// Do something
break;
}
Cependant, je suis préoccupé par quelque chose comme ça.
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;
}
De cette façon, chaque fois que le cas est 0, 1, il fera tout dans l'instruction switch. J'ai vu cela par conception et je ne sais tout simplement pas si je suis d'accord que les instructions switch devraient être utilisées de cette façon. Je pense que le premier exemple de code est très utile et sûr. Le second semble assez dangereux.
Réponses:
Cela peut dépendre de ce que vous considérez comme un échec. Je suis d'accord avec ce genre de chose:
Mais si vous avez une étiquette de cas suivie d'un code qui passe par une autre étiquette de cas, je considérerais presque toujours cela comme un mal. Peut-être que déplacer le code commun vers une fonction et appeler des deux endroits serait une meilleure idée.
Et veuillez noter que j'utilise la définition de la FAQ C ++ de «mal»
la source
C'est une épée à double tranchant. C'est parfois très utile, mais souvent dangereux.
Quand est-ce bon? Lorsque vous voulez que 10 cas soient tous traités de la même manière ...
La seule règle que j'aime est que si jamais vous faites quelque chose d'extraordinaire où vous excluez la pause, vous avez besoin d'un commentaire clair / * FALLTHROUGH * / pour indiquer que c'était votre intention.
la source
if(condition > 1 && condition <10) {condition = 1}; switch(...
sauver des cas (pour une apparence claire) et tout le monde peut voir que vous voulez vraiment que ces cas déclenchent la même action.Avez-vous entendu parler de l'appareil de Duff ? Ceci est un excellent exemple d'utilisation de basculement de commutateur.
C'est une fonctionnalité qui peut être utilisée et qui peut être abusée, comme presque toutes les fonctionnalités du langage.
la source
La transition est vraiment pratique, selon ce que vous faites. Considérez cette façon claire et compréhensible d'organiser les options:
Imaginez faire cela avec if / else. Ce serait un gâchis.
la source
Cela peut être très utile à quelques reprises, mais en général, aucune erreur n'est le comportement souhaité. L'interruption doit être autorisée, mais pas implicite.
Un exemple, pour mettre à jour d'anciennes versions de certaines données:
la source
J'aimerais une syntaxe différente pour les solutions de secours dans les commutateurs, quelque chose comme, errr ..
Remarque: Cela serait déjà possible avec les énumérations, si vous déclarez tous les cas sur votre énumération en utilisant des indicateurs, non? Cela ne sonne pas si mal non plus; les cas pourraient (devraient?) très bien faire déjà partie de votre énumération.
Peut-être que ce serait un bon cas (sans jeu de mots) pour une interface fluide utilisant des méthodes d'extension? Quelque chose comme, euh ...
Bien que ce soit probablement encore moins lisible: P
la source
Comme pour tout: s'il est utilisé avec précaution, il peut être un outil élégant.
Cependant, je pense que les inconvénients justifient largement de ne pas l'utiliser, et finalement de ne plus l'autoriser (C #). Parmi les problèmes figurent:
Bonne utilisation d'un interrupteur / boîtier:
Utilisation Baaaaad d'un interrupteur / boîtier:
Cela peut être réécrit en utilisant des constructions if / else sans aucune perte à mon avis.
Mon dernier mot: évitez les étiquettes de cas fall-through comme dans le mauvais exemple, à moins que vous ne mainteniez un code hérité où ce style est utilisé et bien compris.
la source
C'est puissant et dangereux. Le plus gros problème avec le fall-through est qu'il n'est pas explicite. Par exemple, si vous rencontrez du code fréquemment modifié qui a un commutateur avec des erreurs, comment savez-vous que c'est intentionnel et non un bogue?
Partout où je l'utilise, je m'assure qu'il est correctement commenté:
la source
Utiliser le fall-through comme dans votre premier exemple est clairement acceptable, et je ne le considérerais pas comme un véritable fall-through.
Le deuxième exemple est dangereux et (s'il n'est pas commenté en détail) non évident. J'apprends à mes étudiants à ne pas utiliser de telles constructions à moins qu'ils ne considèrent que cela vaut la peine de lui consacrer un bloc de commentaires, qui décrit qu'il s'agit d'une erreur intentionnelle et pourquoi cette solution est meilleure que les alternatives. Cela décourage une utilisation bâclée, mais cela le rend toujours autorisé dans les cas où il est utilisé à un avantage.
C'est plus ou moins équivalent à ce que nous faisions dans les projets spatiaux lorsque quelqu'un voulait violer la norme de codage: il fallait demander une dispense (et j'ai été appelé à donner des avis sur la décision).
la source
Je n'aime pas que mes
switch
déclarations échouent - elles sont beaucoup trop sujettes aux erreurs et difficiles à lire. La seule exception est lorsque plusieurscase
instructions font toutes exactement la même chose.S'il y a du code commun que plusieurs branches d'une instruction switch veulent utiliser, je l'extraye dans une fonction commune distincte qui peut être appelée dans n'importe quelle branche.
la source
Dans certains cas, l'utilisation de fall-through est un acte de paresse de la part du programmeur - il pourrait utiliser une série de || par exemple, mais utilisez plutôt une série de cas de commutation «fourre-tout».
Cela étant dit, je les ai trouvés particulièrement utiles quand je sais que finalement je vais quand même avoir besoin des options (par exemple dans une réponse de menu), mais que je n'ai pas encore implémenté tous les choix. De même, si vous faites une chute à la fois pour «a» et «A», je trouve qu'il est nettement plus propre d'utiliser le commutateur de chute qu'une instruction if composée.
C'est probablement une question de style et de la façon dont les programmeurs pensent, mais je n'aime généralement pas supprimer les composants d'un langage au nom de la `` sécurité '' - c'est pourquoi je tend davantage vers le C et ses variantes / descendants que, disons, Java. J'aime pouvoir faire des singes avec des pointeurs et autres, même si je n'ai aucune «raison» de le faire.
la source
Fall-through ne doit être utilisé que lorsqu'il est utilisé comme table de saut dans un bloc de code. S'il y a une partie du code avec une interruption inconditionnelle avant plus de cas, tous les groupes de cas doivent se terminer de cette façon.
Tout le reste est "mal".
la source