Est-il une différence significative entre l'utilisation de if/else et switch-case en C#?
Quel est l'avantage/inconvénient de l'utilisation d'un switch
déclaration contre un if/else
en C#. Je ne peux pas imaginer que les grandes d'une différence, d'autres que peut-être le look de votre code.
Est-il une raison pourquoi la IL ou associés les performances d'exécution serait radicalement différent?
Connexes: Ce qui est plus rapide, basculer sur la chaîne ou elseif sur type?
- Related topic: stackoverflow.com/questions/335971/is-switch-case-always-wrong
- Cette question est intéressante dans la théorie pour la majorité des développeurs, sauf si vous vous trouvez souvent l'itération d'UN MILLIARD de fois. (Puis utilisez une instruction switch et passer de 48 à 43 secondes...) Ou dans les mots de Donald Knuth: "Nous devons oublier les petites efficacité, disons environ 97% de l'optimisation prématurée est la racine de tous les maux" en.wikipedia.org/wiki/Program_optimization#When_to_optimize
- J'utilise souvent des si/d'autre à la place de l'interrupteur à cause du vilain portée partagée de l'interrupteur.
Vous devez vous connecter pour publier un commentaire.
Instruction SWITCH seul produit de la même assemblée que les Fi en debug ou en mode de compatibilité. Dans libération, il sera compilé dans saut de la table (par MSIL 'switch' instruction)- qui est O(1).
C# (contrairement à beaucoup d'autres langues) permet également de basculer sur les constantes de chaîne - et cela fonctionne un peu différemment. Il n'est évidemment pas pratique pour construire sauter les tables pour les chaînes de longueurs arbitraires, donc le plus souvent à la substitution seront compilées dans la pile de l'IFs.
Mais si le nombre de conditions est suffisante pour couvrir les frais généraux, C# le compilateur va créer une table de hachage de l'objet, de le remplir avec des constantes de chaîne et de faire une recherche sur la table, suivi par sauter. Table de hachage de recherche n'est pas strictement O(1) et est perceptible à coûts constants, mais si le nombre de cas où des étiquettes est grand, il sera nettement plus rapide que de comparer à chaque constante de chaîne en IFs.
Pour résumer, si le nombre de conditions est de plus de 5 ou alors, préférez BASCULER, SI, sinon utiliser quelle que soit l'air mieux.
En général (en tenant compte de toutes les langues et tous les compilateurs) une instruction switch PEUT PARFOIS être plus efficace que d'un if /else, car il est facile pour un compilateur pour générer sauter les tables à partir d'instructions de commutation. Il est possible de faire la même chose pour les if /else, compte tenu des contraintes appropriées, mais qui est beaucoup plus difficile.
Dans le cas de C#, c'est vrai aussi, mais pour d'autres raisons.
Avec un grand nombre de chaînes de caractères, il existe un important avantage de performance à l'aide d'une instruction switch, parce que le compilateur va utiliser une table de hachage pour mettre en œuvre le saut.
Avec un petit nombre de chaînes de caractères, les performances entre les deux est le même.
C'est parce que dans ce cas, le compilateur C# ne pas générer un saut de la table. Au lieu de cela, il génère MSIL qui est équivalent à if /ELSE blocs.
Il y a un "switch" instruction MSIL que lorsque jitted va utiliser un saut de la table pour mettre en œuvre une instruction switch. Il fonctionne uniquement avec les types integer, toutefois, cette question porte sur les chaînes de caractères).
Pour un petit nombre de chaînes, il est plus efficace pour le compilateur pour générer des SI /d'AUTRE blocs, puis il consiste à utiliser une table de hachage.
Quand j'ai d'abord remarqué, j'ai fait l'hypothèse que, parce que SI /d'AUTRE des blocs ont été utilisés avec un petit nombre de chaînes, que le compilateur n'a la même transformation pour un grand nombre de chaînes.
C'était FAUX. 'IMA' a eu la gentillesse de le signaler à moi (bien...il n'était pas du genre à ce sujet, mais il avait raison et j'avais tort, ce qui est le plus important)
J'ai aussi fait un abruti hypothèse sur l'absence d'un "switch" de l'enseignement en MSIL (j'ai pensé, si il y avait un interrupteur primitive, pourquoi n'ont-ils pas de l'utiliser avec une table de hachage, donc il ne doit pas être un interrupteur de primitives.... ). C'était à la fois tort et incroyablement stupide de ma part. Une fois de plus 'IMA' l'a souligné à moi.
J'ai fait les mises à jour ici parce que c'est la cote la plus élevée de poste, et l'on a accepté la réponse.
Cependant,je l'ai fait Wiki de la Communauté parce que je me dis que je ne mérite pas la REP pour le mal. Si vous obtenez une chance, veuillez jusqu'vote "ima"s post.
Trois raisons de préférer la
switch
:Un compilateur de ciblage du code natif peut souvent compiler une instruction switch en une branche conditionnelle plus indirecte sauter alors qu'une séquence de
if
s nécessite une séquence de branches conditionnelles. En fonction de la densité de cas, un grand nombre de documents savants ont été écrits sur la façon de compiler les cas énoncés de manière efficace; certains d'entre eux sont de la lcc compilateur page. (Lcc était l'un des plus innovants de compilateurs pour les interrupteurs.)Une instruction switch est un choix parmi les alternatives mutuellement exclusives et le commutateur de la syntaxe fait de ce flux de contrôle plus transparent pour le programmeur puis un nid de if-then-else.
Dans certaines langues, y compris certainement ML et Haskell, le compilateur vérifie pour voir si vous avez laissé de côté tout cas. Je considère que c'est l'un des principaux avantages de la ML et Haskell. Je ne sais pas si C# peuvent le faire.
Une anecdote: lors d'une conférence qu'il a donné sur la réception d'une récompense pour l'accomplissement d'une vie, j'ai entendu Tony Hoare dire que, de toutes les choses qu'il a fait dans sa carrière, il y avait trois qu'il était le plus fier:
case
déclaration)Je ne peux pas imaginer de vivre sans
switch
.Le compilateur va optimiser un peu tout dans le même code avec des différences mineures (Knuth, anyone?).
La différence est que l'instruction switch est plus propre que quinze si else qui s'enchaînent.
Amis ne laissez pas les amis de la pile if-else.
En fait, une instruction switch est plus efficace. Le compilateur d'optimiser à une table où avec if/else, il ne peut pas. L'inconvénient est que une instruction switch ne peut pas être utilisé avec les valeurs de la variable.
Vous ne pouvez pas faire:
il doit être
Je n'avais pas voir quelqu'un d'autre soulèvent la (évident, non?) point que la prétendue efficacité de l'avantage de l'instruction switch est en fonction des différents cas d'environ la même probabilité. Dans les cas où un (ou quelques) les valeurs sont beaucoup plus probablement, le si-alors-sinon échelle peut être beaucoup plus rapide, en assurant les cas les plus courants sont d'abord vérifié:
Ainsi, par exemple:
vs
Si x est égal à zéro à 90% du temps, le "if-else" code peut être deux fois plus rapide que le commutateur de code. Même si le compilateur transforme le "switch" dans une sorte d'astuce de la table-driven goto, il persiste à ne pas être aussi rapide qu'une simple vérification de zéro.
switch
-compatible, laswitch
déclaration est mieux (plus lisible, parfois plus rapide). Si vous savez qu'un cas est beaucoup plus probable, vous pouvez tirer que pour former unif
-else
-switch
construire et si c'est sensiblement plus rapide, vous quittez le. (Répéter, si nécessaire.) IMO c'est encore assez lisible. Si leswitch
dégénère et devient trop petite, une regex foyer se font la plupart du travail de la transformer en uneelse if
de la chaîne.souvent, il sera mieux - ie sera plus facile de comprendre ce qu'il se passe. Compte tenu de l'amélioration des performances peut être extrêmement minime, au mieux, le point de vue du code, c'est la différence la plus importante.
Donc, si la si/d'autre à l'air mieux, l'utiliser, sinon utilisez une instruction switch.
Côté sujet, mais je m'inquiète souvent (et plus souvent)
if
/else
etswitch
déclaration à obtenir de façon trop grande avec de trop nombreux cas. Ceux-ci sont souvent mal maintenabilité.Les coupables les plus communs comprennent:
À corriger:
Si vous êtes simplement en utilisant l'instruction if ou else la solution de base est à l'aide de la comparaison ? opérateur
Vous pouvez faire ou de routine dans un commutateur
Ce n'est pas réellement répondre à votre question, mais étant donné, il y aura peu de différence entre les versions compilées, je vous invite à écrire votre code dans une manière qui correspond le mieux à vos intentions. Non seulement il y a une meilleure chance de le compilateur fait ce que vous attendez, mais il sera plus facile pour les autres de maintenir votre code.
Si votre intention est de direction de votre programme basé sur la valeur d'une variable ou d'un attribut, puis une instruction switch représente le mieux cette intention.
Si votre intention est de direction de votre programme en fonction de différentes variables/attributs/des conditions, puis un if/else si la chaîne correspond le mieux à cette intention.
Je le ferai que cody est juste sur les gens oublient la commande break, mais presque aussi souvent que je vois des gens faire compliqué si les blocs où ils obtiennent la { } de mal, donc, les lignes qui doivent être dans l'instruction conditionnelle ne le sont pas. C'est l'une des raisons pour lesquelles je toujours inclure { } sur mon si les déclarations, même si il ya une ligne. Non seulement est-il plus facile à lire, mais si j'ai besoin d'ajouter une autre ligne au conditionnel, je ne peux pas oublier de l'ajouter.
L'instruction switch est certainement le plus rapide, puis un si d'autre si. Il y a speedtest qui ont été fournis par BlackWasp
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx
--Check it out
Mais dépend fortement les possibilités que vous essayez de compte, mais j'essaie d'utiliser une instruction switch à chaque fois que possible.
Que par ce lien, SI vs Commutateur comparaison de l'itération de test à l'aide de l'interrupteur et si la déclaration, c'est comme pour les 1 000 000 000 d'itérations, le Temps pris par Commutateur Instruction=43.0 s & par Si l'Instruction = 48.0 s
Qui est littéralement 20833333 itérations par seconde, Donc, Doit-on vraiment besoin de se concentrer plus,
P. S:Juste pour savoir la différence de performances pour les petites liste de conditions.
Non seulement C#, mais toutes basées sur le C langues, je pense que: parce qu'un changement est limitée à des constantes, il est possible de générer très efficace du code à l'aide d'un "saut de la table". Le cas C est vraiment un bon vieux FORTRAN calculée GOTO, mais le C# de cas est encore de tests à l'encontre d'une constante.
Il n'est pas le cas que l'optimiseur va être en mesure de faire le même code. Considérons, par exemple,
Car ceux-ci sont composés des booléens, le code généré est de calculer une valeur, et de court-circuit. Considérons maintenant l'équivalent
Cela peut être compilé dans
parce que vous êtes implicitement dire au compilateur qu'il n'a pas besoin de calculer la OU et tests d'égalité.
Intérêt de la question. Il en a été question il y a quelques semaines au travail et nous avons trouvé une réponse par écrit un exemple extrait de code et en le regardant dans .NET Réflecteur (réflecteur est génial!! je l'aime).
C'est ce que nous avons découvert:
Valide instruction switch pour autre chose qu'une chaîne est compilé pour IL comme une instruction switch. Toutefois, SI c'est une chaîne, il est réécrit comme un if/else if/else dans IL. Dans notre cas, nous voulions savoir comment les instructions de commutation de comparer les chaînes d'e.g est sensible à la casse etc. et réflecteur rapidement nous a donné une réponse. C'était utile de le savoir.
Si vous voulez faire de la casse de comparer des chaînes de caractères, alors vous pourrait d'une instruction switch car il est plus rapide que l'exécution d'une Chaîne de caractères.Comparer dans un if/else. (Edit: Lire Ce qui est plus rapide, basculer sur la chaîne ou elseif sur type? pour quelques tests de performance) Cependant, si vous vouliez faire un casse, alors il est préférable d'utiliser un si/d'autre que le code résultant est pas assez.
La meilleure règle à suivre est d'utiliser les instructions switch si elle a un sens (sérieusement), e.g:
Si vous avez besoin de manipuler la valeur à introduire dans l'instruction switch (créer une variable temporaire pour basculer contre), alors vous devriez probablement être l'aide d'un if/else contrôle de l'instruction.
Une mise à jour:
Il est effectivement préférable de convertir la chaîne en majuscules (par exemple,
ToUpper()
) comme cela a été apparemment il y a d'autres optimisations que le juste-à-temps compilateur peut le faire comme lorsque comparé à laToLower()
. C'est un micro-optimisation, cependant dans une boucle serrée, il pourrait être utile.Une petite note à part:
Pour améliorer la lisibilité des instructions de commutation essayez ce qui suit:
Mon cs professeur a suggéré de ne pas vous les instructions switch depuis si souvent les gens ont oublié la rupture ou de l'utiliser de manière incorrecte. Je peux pas me rappeler exactement ce qu'il dit, mais quelque chose le long des lignes de regarder quelques séminal base de code qui a montré des exemples de l'instruction switch (ans) avait des tonnes d'erreurs également.
Quelque chose que je viens de remarquer, c'est que vous pouvez combiner les if/else et switch états! Très utile lorsqu'il est nécessaire de vérifier les conditions préalables.
Je Pense Que Switch Est Plus Rapide Que Si Les Conditions
comme voir si Il y a un programme comme :
Écrire un Programme pour saisir n'importe quel nombre entre 1 et 99) et vérifier que tout est en slot a) 1 – 9 fente b) 11 – 19, puis dans la deuxième fente c) 21-29 trois logements et ainsi de suite, jusqu'89-99
Alors Si Vous Avez À Faire Beaucoup de Conditions, Mais le Fils de l'Interrupteur Cas Vous Avez Juste À Taper
il sera aussi Facile
Il Y A De Nombreux Autres Exemples Aussi!
une instruction switch bref c'est une comparaison pour l'égalité. l'événement de clavier ont un grand avantage sur instruction de commutation est alors facile à lire et à écrire du code, puis d'un if elseif instruction, manque un {crochet} peut obtenir troublant ainsi.
Un si elseif déclaration est idéal pour plus, alors une solution si(theAmountOfApples est supérieure à 5 && theAmountOfApples est à moins de 10) enregistrez vos pommes
else if(theAmountOfApples est supérieure à 10 || theAmountOfApples == 100) de vendre vos pommes. Je n'ai pas l'écrire en c# ou c++, mais je ne l'apprendre avant d'apprendre java et ils sont à proximité des langues.
je sais que ce n'est pas exactement la question mais j'ai vraiment besoin de préciser que lorsque vous pensez au sujet de l'efficacité à ce niveau, vous pourriez avoir besoin de plus d'abstraction dans votre code. Vous n'aurez plus besoin de basculer cas, surtout si elle contient la logique. (mon exemple en php).
Maintenant, regardez la redondance du code similaire!
Une possible baisse des instructions de commutation est son manque de multiples conditions. Vous pouvez avoir plusieurs conditions pour le si (le reste), mais pas de cas multiples déclarations avec des conditions différentes dans un commutateur.
Instructions de commutation ne sont pas adaptés pour les opérations logiques au-delà de la portée de Booléenne simple des équations et des expressions. Pour ceux équations Booléennes/expressions, il est tout à fait adéquate, mais pas pour d'autres opérations logiques.
Vous avez beaucoup plus de liberté avec la logique disponible dans les instructions if, mais la lisibilité peut souffrir si la Si la déclaration devient lourd ou mal traités.
Les deux ont leur place en fonction du contexte, de ce que vous êtes confrontés.