Qui a décidé (et sur quels concepts) que la switch
construction (dans de nombreuses langues) doit utiliser break
dans chaque énoncé?
Pourquoi devons-nous écrire quelque chose comme ceci:
switch(a)
{
case 1:
result = 'one';
break;
case 2:
result = 'two';
break;
default:
result = 'not determined';
break;
}
(remarqué cela en PHP et JS; il y a probablement beaucoup d'autres langages qui l'utilisent)
Si switch
est une alternative de if
, pourquoi nous ne pouvons pas utiliser la même construction que pour if
? C'est à dire:
switch(a)
{
case 1:
{
result = 'one';
}
case 2:
{
result = 'two';
}
default:
{
result = 'not determined';
}
}
On dit que cela break
empêche l'exécution du bloc suivant celui en cours. Mais, est-ce que quelqu'un se heurte réellement à la situation, où il était nécessaire d'exécuter le bloc actuel et les suivants? Je n'ai pas Pour moi, break
c'est toujours là. Dans chaque bloc. Dans chaque code.
conditions
trejder
la source
la source
CASE
instruction de manière équivalente à un bloc géant if / elseif.case 'a': case 'A': case 'b': case 'B'
mais surtout parce que je ne peux pas fairecase in [ 'a', 'A', 'b', 'B' ]
. Une question légèrement meilleure est, dans mon langage préféré actuel (C #), la pause est obligatoire et il n’ya pas de chute implicite; l'oublibreak
est une erreur de syntaxe ...: \case TOKEN_A: /*set flag*/; case TOKEN_B: /*consume token*/; break; case TOKEN_C: /*...*/
break
est présent n'importe où» est une règle beaucoup plus simple à appliquer que «Ne pas émettre de saut sifallthrough
est présent dans unswitch
».Réponses:
C a été l’une des premières langues à avoir l’
switch
énoncé sous cette forme, et toutes les autres langues principales en ont hérité, choisissant pour la plupart de conserver la sémantique C par défaut. les moins importants que de garder le comportement auquel tout le monde était habitué.Quant à la raison pour laquelle C a été conçu de cette manière, il découle probablement du concept de C en tant qu '"assemblage portable". L'
switch
instruction est fondamentalement une abstraction d'une table de branche , et une table de branche a également un impact implicite et nécessite une instruction de saut supplémentaire pour l'éviter.Donc, fondamentalement, les concepteurs de C ont également choisi de conserver la sémantique de l’assembleur par défaut.
la source
switchon
.when
.Parce que
switch
n'est pas une alternative deif ... else
déclarations dans ces langues.En utilisant
switch
, nous pouvons associer plus d'une condition à la fois, ce qui est très apprécié dans certains cas.Exemple:
la source
more than one block ... unwanted in most cases
Je ne suis pas d'accord avec toi.break
. Mais oui, autant que je sache, le périphérique de Duff ne fonctionne pas en C #.C# does not support an implicit fall through from one case label to another
. Vous pouvez tomber, mais vous ne pouvez pas oublier une pause par accident.if..else
mais dans certaines situations, ilswitch..case
serait préférable. L'exemple ci-dessus serait un peu complexe si nous utilisons if-else.Cela a été demandé pour Stack Overflow dans le contexte de C: Pourquoi l'instruction switch a-t-elle été conçue pour nécessiter une pause?
Pour résumer la réponse acceptée, c'était probablement une erreur. La plupart des autres langues ont probablement juste suivi C. Cependant, certaines langues telles que C # semblent avoir résolu ce problème en autorisant les retombées - mais uniquement lorsque le programmeur le dit explicitement (source: le lien ci-dessus, je ne parle pas C # moi-même) .
la source
/* FALLTHRU */
commentaire dans la réponse liée par @Tapio ci-dessus, pour prouver que vous le pensiez bien.goto case
, comme le lien, ne montre pas pourquoi cela fonctionne si bien. Vous pouvez toujours empiler plusieurs cas comme ci-dessus, mais dès que vous insérez du code, vous devez disposer d'un explicitegoto case whatever
pour passer au cas suivant ou vous obtenez un compilateur. Si vous me demandez, des deux, la possibilité d'empiler des cas sans se soucier de la négligence par inadvertance est de loin une fonctionnalité meilleure que de permettre une chute explicite avecgoto case
.Je vais répondre avec un exemple. Si vous voulez lister le nombre de jours pour chaque mois de l’année, il est évident que certains mois en ont 31, 30 et 28/29. Cela ressemblerait à ceci,
Ceci est un exemple où plusieurs observations ont le même effet et sont toutes regroupées. Il y avait évidemment une raison pour le choix du mot clé break et non pas le if ... sinon si construit.
La principale chose à prendre en compte ici est qu'une instruction switch avec beaucoup de cas similaires n'est pas un if ... sinon si ... sinon si ... sinon pour chacun des cas, mais plutôt si (1, 2, 3) ... sinon si (4,5,6) sinon ...
la source
if
sans aucun avantage. Peut-être que si votre exemple donnait un nom ou effectuait un travail spécifique à un mois en plus des retombées, l'utilité des retombées serait plus évidente? (sans dire si on DEVRAIT ou non en premier lieu)Il y a deux situations où «passer à travers» d'un cas à l'autre peut arriver - le cas vide:
et le cas non vide
Nonobstant la référence au périphérique de Duff , les instances légitimes pour le second cas sont rares et généralement interdites par les normes de codage et signalées lors d'une analyse statique. Et là où il se trouve, il est le plus souvent dû à l’omission de a
break
.Le premier est parfaitement sensé et commun.
Pour être honnête, je ne vois aucune raison d’avoir besoin de l’
break
analyseur de langage et de l’analyseur de langage sachant qu’un corps de cas vide est un échec, alors qu’un cas non vide est autonome.Il est dommage que le panel ISO C semble plus préoccupé par l'ajout de nouvelles fonctionnalités (non désirées) mal définies au langage, plutôt que par la correction des fonctionnalités non définies, non spécifiées ou définies par la mise en œuvre, sans parler de l'illogique.
la source
Ne pas forcer le
break
permet un certain nombre de choses qui pourraient autrement être difficiles à faire. D'autres ont noté des cas de regroupement, pour lesquels il existe un certain nombre de cas non triviaux.Un cas où il est impératif de
break
ne pas l'utiliser est le périphérique de Duff . Ceci est utilisé pour " dérouler " les boucles où il peut accélérer les opérations en limitant le nombre de comparaisons requises. Je pense que l’utilisation initiale permettait une fonctionnalité qui était auparavant trop lente avec une boucle entièrement enroulée. Il négocie la taille du code pour la vitesse dans certains cas.Il est judicieux de remplacer le
break
avec un commentaire approprié, si le cas contient du code. Sinon, quelqu'un corrigera les manquantsbreak
et introduira un bogue.la source
En C, où l’origine semble être, le bloc de code de l’
switch
instruction n’est pas une construction spéciale. C'est un bloc de code normal, tout comme un bloc sous uneif
instruction.case
etdefault
sont des étiquettes de saut à l'intérieur de ce bloc, spécifiquement liées àswitch
. Ils sont traités comme des étiquettes de saut normalesgoto
. Il y a une règle spécifique qui est importante ici: les étiquettes de saut peuvent être presque partout dans le code, sans interrompre le flux de code.En tant que bloc de code normal, il n'est pas nécessaire que ce soit une instruction composée. Les étiquettes sont également facultatives. Ce sont des
switch
déclarations valables en C:La norme C elle-même donne ceci à titre d'exemple (6.8.4.2):
En outre,
default
est une étiquette de saut aussi, et peut donc être n'importe où, sans avoir à être le dernier cas.Cela explique également le périphérique de Duff:
Pourquoi la chute? Parce que dans le flux de code normal dans un bloc de code normal, l'instruction suivante est attendue , tout comme vous le feriez dans un
if
bloc de code.Je suppose que la raison en était la facilité de mise en œuvre. Vous n'avez pas besoin de code spécial pour analyser et compiler un
switch
bloc, en prenant soin de règles spéciales. Vous venez de l'analyser comme n'importe quel autre code et vous ne devez vous soucier que des étiquettes et de la sélection de saut.Une question intéressante de suivi de tout cela est si les déclarations imbriquées suivantes affichent "Terminé". ou pas.
La norme C s'en occupe (6.8.4.2.4):
la source
Plusieurs personnes ont déjà évoqué la notion d'association de plusieurs conditions, ce qui est très précieux de temps en temps. Cependant, la possibilité de faire correspondre plusieurs conditions ne nécessite pas nécessairement que vous fassiez exactement la même chose pour chaque condition correspondante. Considérer ce qui suit:
Il existe deux manières différentes de faire correspondre des ensembles de conditions multiples. Avec les conditions 1 et 2, ils tombent simplement dans la même parcelle de code et font exactement la même chose. Aux conditions 3 et 4, toutefois, bien que les deux appels aboutissent
doSomething3And4()
, seuls 3 appels sont nécessairesdoSomething3()
.la source
case 2
déclenchement, donc si nous voulons être corrects (et nous le faisons), le réel le nom de la fonction devrait êtredoSomethingBecause_1_OR_2_OR_1AND2()
ou quelque chose du genre (bien que le code légitime dans lequel une immuable corresponde à deux cas différents tout en restant bien écrit, le code est pratiquement inexistant, il devrait donc au moins le resterdoSomethingBecause1or2()
)doSomething[ThatShouldBeDoneInTheCaseOf]1And[InTheCaseOf]2()
. Cela ne fait pas référence à la logique et / ou.Pour répondre à deux de vos questions.
Pourquoi C a-t-il besoin de pauses?
Cela revient aux racines de Cs en tant qu '"assembleur portable". Où psudo code comme celui-ci était commun: -
l'instruction switch a été conçue pour fournir des fonctionnalités similaires à un niveau supérieur.
Avons-nous des interrupteurs sans pause?
Oui, c'est assez courant et il y a quelques cas d'utilisation;
Premièrement, vous souhaiterez peut-être prendre la même mesure dans plusieurs cas. Nous faisons cela en empilant les cas les uns sur les autres:
Un autre cas d'utilisation courant dans les machines d'état est qu'après le traitement d'un état, nous souhaitons immédiatement entrer et traiter un autre état:
la source
L'instruction Break est une instruction sautante qui permet à l'utilisateur de quitter le commutateur englobant le plus proche (pour votre cas), pendant que vous faites, pour ou pour chaque. c'est aussi simple que cela.
la source
Je pense qu'avec tout ce qui est écrit ci-dessus - le principal résultat de ce fil est que si vous voulez concevoir un nouveau langage - la valeur par défaut devrait être que vous n'avez pas besoin d'ajouter une
break
déclaration et que le compilateur la traitera comme si vous l'aviez fait.Si vous souhaitez que le cas rare où vous souhaitez passer à la prochaine affaire - indiquez-le simplement avec une
continue
déclaration.Cela peut être amélioré de manière à ce que cela ne se produise que si vous utilisez des accolades à l'intérieur du cas, de sorte que l'exemple avec les mois précédents de plusieurs cas exécutant le même code exact - fonctionne toujours comme prévu sans avoir besoin de
continue
.la source
*
,&
,static
etc.