32 votes

Y a-t-il jamais une raison d'utiliser goto dans le code .NET moderne?

Je viens de trouver ce code dans le réflecteur dans le .NET de base des bibliothèques...

    if (this._PasswordStrengthRegularExpression != null)
    {
        this._PasswordStrengthRegularExpression = this._PasswordStrengthRegularExpression.Trim();
        if (this._PasswordStrengthRegularExpression.Length == 0)
        {
            goto Label_016C;
        }
        try
        {
            new Regex(this._PasswordStrengthRegularExpression);
            goto Label_016C;
        }
        catch (ArgumentException exception)
        {
            throw new ProviderException(exception.Message, exception);
        }
    }
    this._PasswordStrengthRegularExpression = string.Empty;
Label_016C:
    ... //Other stuff

J'ai entendu tous les "tu ne dois pas utiliser goto sur la peur de l'exil à l'enfer pour l'éternité" spiel. J'ai toujours tenu MS codeurs en assez haute estime, et même si je suis pas d'accord avec toutes leurs décisions, j'ai toujours respecté leur raisonnement.

Donc, est - il une bonne raison pour le code comme ceci que je suis absent? A présent code extrait viens de mettre ensemble par une maladroite développeur? ou est .NET réflecteur retour inexactes code?

J'espère qu'il y est une bonne raison, et je suis juste aveuglément la rater.

Merci pour tous les commentaires

45voto

Hans Passant Points 475940

Réflecteur n'est pas parfait. Le code de cette méthode est disponible à partir de la Source de Référence. Il est situé dans npd\fx\src\xsp\system\web\security\admembershipprovider.cs:

        if( passwordStrengthRegularExpression != null )
        { 
            passwordStrengthRegularExpression = passwordStrengthRegularExpression.Trim();
            if( passwordStrengthRegularExpression.Length != 0 ) 
            { 
                try
                { 
                    Regex regex = new Regex( passwordStrengthRegularExpression );
                }
                catch( ArgumentException e )
                { 
                    throw new ProviderException( e.Message, e );
                } 
            } 
        }
        else 
        {
            passwordStrengthRegularExpression = string.Empty;
        }

Notez comment il a échoué à détecter la dernière clause else et compensé avec un goto. Il est presque certainement déclenché par les blocs try/catch à l'intérieur du if() consolidés.

Clairement, vous aurez envie de favoriser le code source au lieu de la décompilé version. Les commentaires sont elles-mêmes très utile et vous pouvez compter sur la source exacte. Eh bien, pour la plupart exactes, il y a des dommages mineurs à partir d'un buggy de post-traitement de l'outil, qui a supprimé les noms de Microsoft programmeurs. Les identificateurs sont parfois remplacés par des tirets, et le code est répété deux fois. Vous pouvez télécharger les sources ici.

12voto

heisenberg Points 6120

Ce n'est probablement pas dans le code source, c'est juste à quoi ressemble le code désassemblé.

12voto

Maynza Points 438

J'ai vu goto utilisé pour sortir des boucles imbriquées:

http://stackoverflow.com/questions/863172/how-can-i-break-out-of-two-nested-for-loops-in-objective-c

Je ne vois rien de mal à l'utiliser de cette façon.

11voto

Simon Gillbee Points 1906

Il y a plusieurs utilisations valides pour goto dans .NET (C# en particulier):

La simulation de l'Instruction Switch Automne-par le biais de la Sémantique.

Ceux qui viennent de C++ de fond sont utilisés pour écrire les instructions switch automatiquement en automne, à travers les cas, sauf s'il est explicitement mis fin à la pause. Pour C#, seulement trivial (vide) cas de chute à travers.

Par exemple, en C++

int i = 1;
switch (i)
{
case 1:
  printf ("Case 1\r\n");
case 2:
  printf ("Case 2\r\n");
default:
  printf ("Default Case\r\n");
  break;
}

Dans ce code C++ de la sortie est:

Cas 1
Cas 2
Cas Par Défaut

Ici est similaire de code C#:

int i = 1;
switch (i)
{
case 1:
  Console.Writeline ("Case 1");
case 2:
  Console.Writeline ("Case 2");
default:
  Console.Writeline ("Default Case");
  break;
}

Comme l'a écrit, ce ne sera pas compilée. Il y a plusieurs erreurs de compilation qui ressemblent à ceci:

Le contrôle ne peut pas tomber d'un seul cas de l'étiquette ("cas 1:') à l'autre

L'ajout d'instructions goto faire fonctionner:

int i = 1;
switch (i)
{
case 1:
    Console.WriteLine ("Case 1");
    goto case 2;
case 2:
    Console.WriteLine("Case 2");
    goto default;
default:
    Console.WriteLine("Default Case");
    break;
}

... les autres goto utiliser en C#, c'est...

Les Boucles infinies et Déroulé de la Récursivité

Je ne vais pas entré dans les détails ici, car il est moins utile, mais parfois nous avons écrire une boucle infinie à l'aide de while(true) des constructions qui sont explicitement dénoncé avec un break ou ré-exécuté avec un continue déclaration. Cela peut se produire lorsque nous essayons de simuler récursive des appels de méthode, mais n'ont pas de contrôle sur le champ d'application potentiel de la récursivité.

Vous pouvez bien évidemment refactoriser en while(true) boucle ou de refactoriser le code dans une méthode distincte, mais également à l'aide d'une étiquette et d'une instruction goto fonctionne.

Cette utilisation de goto est plus discutable, mais encore quelque chose de la peine de garder dans votre esprit comme une option dans de très rares circonstances.

8voto

uncle brad Points 1134

Je ne suis pas fou des gotos, mais dire qu'ils ne sont jamais valides est idiot.

J'en ai utilisé une fois pour corriger un défaut dans un morceau de code particulièrement salissant. Refactoriser le code et le tester n'aurait pas été pratique compte tenu de la contrainte de temps.

D'ailleurs, n'avons-nous pas tous vu des constructions conditionnelles qui étaient si mal codées qu'elles donnent l'impression que les gotos sont bénins?

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