web-dev-qa-db-fra.com

Est-ce que quelqu'un utilise encore [goto] en C # et si oui pourquoi?

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.

Aller à la définition du mot clé

95
Brian Scott

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.

86
Heinzi

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

62
V4Vendetta

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é ...

22
Jon Skeet

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.

8
Jesus Ramos

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.

6
Jordão

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.

5
Justin

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.

2
Jodrell