Je me demandais si quelqu'un utilisait encore la syntaxe de mot-clé "goto" en C # et quelles en étaient les raisons.
J'ai tendance à voir dans les déclarations qui poussent le lecteur à contourner le code comme une mauvaise pratique, mais je me suis demandé s'il existait des scénarios crédibles d'utilisation d'une telle syntaxe.
Il existe quelques cas (rares) où goto peut réellement améliorer la lisibilité. En fait, la documentation à laquelle vous avez accédé énumère deux exemples:
Une utilisation courante de goto est de transférer le contrôle sur une étiquette de casse de commutateur spécifique ou l'étiquette par défaut dans une instruction switch.
La déclaration goto est également utile pour sortir des boucles profondément imbriquées.
Voici un exemple pour le dernier:
for (...) {
for (...) {
...
if (something)
goto end_of_loop;
}
}
end_of_loop:
Bien sûr, il existe également d'autres moyens de contourner ce problème, tels que refactoriser le code dans une fonction, utiliser un bloc factice autour de celui-ci, etc. (voir cette question pour plus de détails). En remarque, les concepteurs de langage Java ont décidé d'interdire complètement goto et d'introduire une instruction libellée.
Je me souviens de cette partie
switch (a)
{
case 3:
b = 7;
// We want to drop through into case 4, but C# doesn't let us
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}
À quelque chose comme ça
switch (a)
{
case 3:
b = 7;
goto case 4;
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}
Reportez-vous This
Je l'utilise beaucoup dans Eduasync pour montrer le type de code que le compilateur génère pour vous lors de l'utilisation de méthodes asynchrones en C # 5. Vous verriez la même chose dans des blocs d'itérateur.
En code "normal" cependant, je ne me souviens plus de la dernière fois que je l'ai utilisé ...
goto est idéal pour rompre de nombreuses boucles où la rupture ne fonctionnerait pas bien (par exemple en cas d'erreur), et comme l'a dit Kragen, goto est utilisé par le compilateur pour générer des instructions switch et d'autres éléments.
Je ne me rappelle pas avoir jamais utilisé goto
. Mais peut-être cela améliore l'intention d'une boucle permanente que vous ne voulez vraiment jamais quitter (no break
, mais vous pouvez toujours return
ou throw
):
forever: {
// ...
goto forever;
}
Là encore, une simple while (true)
devrait suffire ...
En outre, vous pouvez utiliser dans une situation où vous souhaitez que la première itération d’une boucle commence au milieu de la boucle: look ici pour un exemple.
Le compilateur utilise les instructions goto
dans divers morceaux de code généré, par exemple dans les types de bloc itérateur générés (générés lors de l’utilisation de la commande yield return
mot clé - Je suis presque sûr que les types de sérialisation XML générés contiennent également quelques instructions goto
.
Voir Détails d'implémentation de bloc Iterator: machines d'état générées automatiquement pour plus de détails sur pourquoi/comment le compilateur C # gère cela.
Hormis le code généré, l'utilisation d'une instruction goto
dans le code normal n'est pas une bonne raison - cela rend le code plus difficile à comprendre et, partant, davantage sujet aux erreurs. En revanche, utiliser goto
dans le code généré de cette manière peut simplifier le processus de génération et convient normalement car personne ne lit (ni ne modifie) le code généré et il n’ya aucune chance que des erreurs soient commises la machine est en train d'écrire.
Voir Instruction Go-to considérée comme nuisible pour un argument contre goto
ainsi qu'un élément classique de l'historique de programmation.
Le processeur implémente au moins un instruction de saut et je suis sûr que beaucoup d'instructions utilisent celles de leur implémentation ou interprétation.
L’un des avantages de l’utilisation d’une langue (génération) rd ou 4th est que ces détails physiques nous sont abstraits. Bien que nous devrions être conscients de la loi de l'abstraction qui fuit , je pense que nous devrions également utiliser notre outils tels qu'ils sont destinés (désolé). Si j’écrivais du code et que goto
me semblait une bonne idée, il serait temps de refactoriser. Le but d'un langage structuré est d'éviter ces "sauts" et de créer un flux logique dans notre ingénierie.
Je devrais éviter l'utilisation de break
mais je ne peux pas négliger les avantages liés aux performances. Cependant, si j'ai des boucles imbriquées qui doivent mutuellement break
, il est temps de refactoriser.
Si quelqu'un peut proposer une utilisation de goto
qui semble meilleure que le refactoring, je retirerai ma réponse avec plaisir.
J'espère que je ne suis pas coupable de m'être précipitée au " remise à vélo " ici. Comme le dit Kragen, ce qui est suffisant pour Dijkstra me suffit.