Question

La compilation du code suivant échoue: "Une variable locale nommée" st "ne peut pas être déclarée dans cette portée car elle donnerait un sens différent à" st ", qui est déjà utilisé dans une portée" enfant "pour indiquer quelque chose. sinon " ;:

        var l = new List<string>();
        l.Find(st => st.EndsWith("12"));
        string st = "why this fails?";

Je comprends pourquoi cela ne fonctionnera pas:

        string preParent = "";
        {
            string preParent = "Should fail cause we change the meaning";
        }

Lorsque nous procédons comme suit, nous obtenons "CS0103: le nom 'postParent' n'existe pas dans le contexte actuel":

        {
            string postParent=string.Empty;
        }
        postParent = "Should this work?";

Ce que je ne comprends pas, c’est pourquoi le compilateur est assez intelligent pour voir que postParent n’est pas dans la portée, mais ne me laisse pas définir une nouvelle variable qui porte le même nom qu’une variable utilisée dans une portée enfant (qui est évidemment hors de portée à ce stade).

Le compilateur applique-t-il simplement la portée en refusant de me laisser utiliser la variable? Si c'est le cas, cela a du sens.

============

Modifié:

Je suppose que ce que je trouve également intéressant, c'est comment vous pouvez avoir la même variable dans deux étendues enfants avec une seule méthode, donc c'est valide:

        {
            string thisWorks= string.Empty;
        }
        {
            string thisWorks= "Should this work?";
        }

Je suis juste un peu curieux que vous puissiez avoir deux variables portant le même nom tant qu'elles sont au même niveau (si vous regardez la portée comme un arbre). Cela a du sens car vous pouvez avoir des variables locales dans deux méthodes de la même classe avec le même nom.

Je suis juste surpris que le compilateur soit capable de se différencier et de permettre cela, alors qu'il ne permet pas la variable postParent. Et s’agit-il d’une limitation technique ou d’une décision de conception? C’est ce que j’essaie vraiment de faire; -)

Était-ce utile?

La solution

Oui, le compilateur applique la portée. Notez que la portée d'une variable est le bloc lexical dont elle fait partie - pas seulement à partir du point de déclaration, mais toute la portée.

Le compilateur se plaint car l’affectation à postParent ne fait pas partie de sa portée (il ne s’agit que des accolades imbriquées). Si vous tentiez de déclarer une nouvelle variable au moment où vous assignez actuellement à postParent , le problème serait lié au bloc imbriqué, car la portée de postParent inclurait cette bloc imbriqué, même si c'était avant la déclaration.

Les étendues sont décrites dans la section 3.7 de la spécification C # 3.0.

MODIFIER: pour répondre à votre question, modifiez-la.

Il n'y a que deux règles simples:

  • vous ne pouvez pas déclarer une variable locale lorsqu'une autre variable locale portant le même nom est dans la portée
  • la portée d'une variable locale est le bloc dans lequel la déclaration se produit

Je suis sûr que le langage aurait pu être conçu de telle sorte que le champ d'application n'ait commencé qu'au moment de la déclaration, mais je pense qu'il est plus simple (en termes de complexité du langage) de considérer les champs comme de simples blocs - donc toutes les variables locales déclarées dans le même bloc a la même portée, par exemple. Cela simplifie également la vie lorsque l’on considère les variables capturées - car ce qui est capturé dépend de la portée, et les étendues imbriquées rendent la vie intéressante ...

EDIT: La spécification de langue a ceci à dire à propos de l'exemple d'expression lambda original - c'est la section 7.14.1:

  

L'option   anonyme-fonction-signature d'un   fonction anonyme définit les noms   et éventuellement les types du formel   paramètres pour la fonction anonyme.   La portée des paramètres de la   fonction anonyme est la   corps-fonction anonyme. Ensemble avec   la liste des paramètres (si fournie), la   anonymous-method-body constitue un   espace de déclaration. Pour cette raison, il   est une erreur de compilation pour le nom   d'un paramètre de l'anonyme   fonction pour correspondre au nom d'un local   variable, constante locale ou paramètre   dont la portée comprend   anonymous-method-expression ou   expression lambda.

Est-ce que cela vous aide?

Autres conseils

Vous déclarez une variable dans une portée limitée et essayez de l'utiliser en dehors de cette portée. Le compilateur suppose que vous ne voulez pas y accéder, vous pouvez donc déclarer une variable du même nom ailleurs dans le fichier. Vous essayez de faire le vieux tour C en supposant que la variable vivra immédiatement hors de la portée. Par exemple, cela fonctionnait dans les anciennes versions de C / C ++ mais ne le fait plus.

for (int i=0; i<10; i++)
{
    cout <<”In the loop i is “<< i << endl;
}
cout << “outside of the loop i is “ << i << endl; //this only compiles with old C/C++ compilers.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top