65 votes

Pourquoi Switch/Case et non If/Else If ?

Cette question s'adresse principalement à C/C++, mais je suppose que d'autres langages sont également concernés.

Je n'arrive pas à comprendre pourquoi on utilise encore le switch/case au lieu du if/else if. Cela ressemble beaucoup à l'utilisation de goto's, et donne le même genre de code désordonné, alors que les mêmes résultats pourraient être obtenus avec if/else if d'une manière beaucoup plus organisée.

Pourtant, je vois ces blocs assez souvent. Un endroit commun pour les trouver est près d'une boucle de message (WndProc...), alors que ce sont les endroits où ils causent le plus de dégâts : les variables sont partagées tout au long du bloc, même quand ce n'est pas approprié (et ne peuvent pas être initialisées à l'intérieur). Il faut faire très attention à ne pas laisser tomber les break, et ainsi de suite...

Personnellement, j'évite de les utiliser, et je me demande si je ne manque pas quelque chose ?

Sont-ils plus efficaces que les if/else ? Sont-elles perpétuées par la tradition ?

168voto

qrdl Points 17813

Pour résumer mon message initial et mes commentaires, il y a plusieurs avantages à switch déclaration sur if / else déclaration :

  1. Code nettoyeur. Code avec de multiples enchaînements if / else if ... l'apparence est désordonnée et difficile à entretenir - switch donne une structure plus propre.

  2. Performance. Pour les case valeurs le compilateur génère une table de saut, pour une recherche binaire ou une série de if / else donc dans le pire des cas switch est aussi rapide que if / else mais généralement plus rapide. Bien que certains compilateurs puissent optimiser de manière similaire if / else .

  3. L'ordre des tests n'a pas d'importance. Pour accélérer les séries de if / else les tests doivent être effectués en priorité sur les cas les plus probables. Avec switch / case Le programmeur n'a pas besoin d'y penser.

  4. Le défaut peut être n'importe où. Avec if / else le cas par défaut doit se situer à la toute fin - après le dernier else . Sur switch - default peut se trouver n'importe où, là où le programmeur le trouve le plus approprié.

  5. Code commun. Si vous avez besoin d'exécuter un code commun pour plusieurs cas, vous pouvez omettre l'option break et l'exécution tombera à l'eau - ce que vous ne pouvez pas faire avec if / else . (Une bonne pratique consiste à placer un commentaire spécial /* FALLTHROUGH */ pour de tels cas - lint le reconnaît et ne se plaint pas, sans ce commentaire il se plaint car c'est une erreur courante d'oublier break ).

Merci à tous les commentateurs.

12 votes

+1 sur la mention de la table de saut (pour les valeurs denses). Ou une recherche binaire, si les valeurs sont clairsemées :-)

4 votes

+1,. De plus, l'ordre n'a pas d'importance dans le switch, ce qui le rend intéressant dans certains cas, comme switch(x) { default : assert(0 && "dunno !") ; other-cases-here } ;

1 votes

@litb : Je suis presque sûr que vous avez tort : switch(a){case 1 : printf("1") ; case 2 : printf("2") ; break;} imprimerait "12" pour a==1, donc l'ordre compte.

31voto

Eric H. Points 1401

Eh bien, l'une des raisons est la clarté.....

si vous avez un commutateur/case, alors l'expression ne peut pas changer.... c'est-à-dire

switch (foo[bar][baz]) {
case 'a':
    ...
    break;
case 'b': 
    ...
    break;
}

alors qu'avec if/else, si vous écrivez par erreur (ou intentionnellement) :

if (foo[bar][baz] == 'a') {
    ....
}
else if (foo[bar][baz+1] == 'b') {
    ....
}

les personnes lisant votre code se demanderont "les expressions foo étaient-elles censées être les mêmes", ou "pourquoi sont-elles différentes" ?

17voto

dfa Points 54490

N'oubliez pas que la fonction "case/select" offre une flexibilité supplémentaire :

  • La condition est évaluée une fois
  • est suffisamment flexible pour permettre de construire des choses comme le Dispositif de Duff
  • fallthrough (alias cas sans casse)

ainsi que il s'exécute beaucoup plus rapidement (par le biais d'une table de saut/de consultation) * historiquement

0 votes

Vous supposez que les concepteurs de compilateurs ne peuvent pas comprendre comment convertir une série de if/eles en une table de saut, ou avez-vous réellement vérifié cela avec un compilateur des 10 dernières années ?

0 votes

Vous avez raison, bien sûr. Laissez-moi vous expliquer que, d'un point de vue historique, le switch est beaucoup plus rapide que le if/else, n'est-ce pas ?

0 votes

Tout compilateur digne de ce nom n'évaluera la condition qu'une seule fois dans une chaîne if/else. Et il générera une table de saut similaire. (À condition que vous ayez codé la chaîne if/else comme le switch/case, c'est-à-dire sans modifier la condition, etc.)

12voto

Joseph Paterson Points 306

Rappelez-vous également que les instructions de commutation permettent de poursuivre le flux de contrôle, ce qui vous permet de combiner joliment les conditions tout en vous permettant d'ajouter du code supplémentaire pour certaines conditions, comme dans le morceau de code suivant :

switch (dayOfWeek)
{
    case MONDAY:
        garfieldUnhappy = true;
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
       weekDay = true;
       break;
    case SATURDAY:
       weekendJustStarted = true;
    case SUNDAY:
       weekendDay = true;
       break;
}

Utilisation de if/else les déclarations ici à la place ne seraient pas aussi agréables.

if (dayOfWeek == MONDAY)
{
    garfieldUnhappy = true;
}
if (dayOfWeek == SATURDAY)
{
    weekendJustStarted = true;
}
if (dayOfWeek == MONDAY || dayOfWeek == TUESDAY || dayOfWeek == WEDNESDAY
    || dayOfWeek == THURSDAY || dayOfWeek == FRIDAY)
{
    weekDay = true;
}
else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY)
{
    weekendDay = true;
}

10voto

Eric Petroelje Points 40734

S'il y a beaucoup de cas, l'instruction switch semble plus propre.

C'est également très pratique lorsque vous avez plusieurs valeurs pour lesquelles vous souhaitez obtenir le même comportement. L'utilisation de plusieurs instructions "case" qui aboutissent à une seule mise en œuvre est beaucoup plus facile à lire qu'un if( this || that || someotherthing || ... ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X