Pourquoi un nom de variable en double ne peut-il pas être déclaré dans une étendue locale nestede?

Sur la base de cette question récente, je ne comprends pas la réponse fournie. On dirait que vous devriez pouvoir faire quelque chose comme ça, puisque leurs scopes ne se chevauchent pas

static void Main() { { int i; } int i; } 

Ce code ne parvient pas à comstackr avec l’erreur suivante:

Une variable locale nommée “i” ne peut pas être déclarée dans cette scope car elle donnerait un sens différent à “i”, qui est déjà utilisé dans une scope “enfant” pour désigner autre chose

Je ne pense pas qu’aucune des réponses obtenues jusqu’à présent ait vraiment trouvé la ligne cruciale de la spécification.

De la section 8.5.1:

La scope d’une variable locale déclarée dans une déclaration de variable locale est le bloc dans lequel la déclaration se produit . C’est une erreur de faire référence à une variable locale dans une position textuelle qui précède le déclarant de variable locale de la variable locale. Dans le cadre d’une variable locale, il s’agit d’une erreur de compilation pour déclarer une autre variable locale ou constante portant le même nom.

(Soulignez le mien.)

En d’autres termes, la scope de la variable “later” inclut la partie du bloc avant la déclaration – c’est-à-dire qu’elle inclut le bloc “inner” contenant la variable “previous”.

Vous ne pouvez pas vous référer à la dernière variable à un endroit antérieur à sa déclaration – mais elle est toujours dans le champ d’application.

“L’étendue de la variable locale ou constante s’étend jusqu’à la fin du bloc en cours. Vous ne pouvez pas déclarer une autre variable locale portant le même nom dans le bloc actuel ou dans des blocs nesteds.” C # 3.0 en bref, http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/

“L’espace de déclaration de la variable locale d’un bloc inclut tous les blocs nesteds. Ainsi, dans un bloc nested, il n’est pas possible de déclarer une variable locale portant le même nom qu’une variable locale dans un bloc englobant.” Étendues variables, MSDN, http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx

En passant, c’est tout à fait le contraire de JavaScript et des règles de cadrage F #.

De la spécification du langage C #:

L’espace de déclaration de la variable locale d’un bloc inclut tous les blocs nesteds. Ainsi, dans un bloc nested, il n’est pas possible de déclarer une variable locale portant le même nom qu’une variable locale dans un bloc englobant.

Essentiellement, ce n’est pas autorisé car, en C #, leurs scopes se chevauchent.

edit: Juste pour clarifier, la scope de C # est résolue au niveau du bloc, pas ligne par ligne. Donc, s’il est vrai que vous ne pouvez pas vous référer à une variable dans le code qui précède sa déclaration, il est également vrai que son étendue s’étend jusqu’au début du bloc.

Cela a été une règle en C # à partir de la première version.

Autoriser les étendues qui se chevauchent ne ferait que créer de la confusion (des programmeurs, pas du compilateur).

Donc, il a été interdit à dessein.

Ce n’est pas une question de champs d’application qui se chevauchent. En C #, un nom simple ne peut pas signifier plus d’une chose dans un bloc où il est déclaré. Dans votre exemple, le nom i signifie deux choses différentes dans un même bloc externe.

En d’autres termes, vous devriez pouvoir déplacer une déclaration de variable à n’importe quel endroit du bloc où elle a été déclarée sans provoquer le chevauchement des étendues. Depuis que vous avez changé votre exemple pour:

 static void Main() { int i; { int i; } } 

Si les scopes des différentes variables i se chevauchaient, votre exemple est illégal.

Pour C #, ISO 23270 ( Technologies de l’information – Langages de programmation – C # ), §10.3 ( Déclarations ) dit:

Chaque bloc , switch-block , for-statement , foreach-statement ou using-statement crée un espace de déclaration pour les variables locales et les constantes locales appelé espace de déclaration de variable locale . Les noms sont introduits dans cet espace de déclaration par le biais de déclarations de variables locales et de déclarations constantes locales .

Si un bloc est le corps d’un constructeur, d’une méthode ou d’une déclaration d’opérateur d’instance, ou un accesseur get ou set pour une déclaration d’indexeur, les parameters déclarés dans une telle déclaration sont membres de l’espace de déclaration de variable locale du bloc.

Si un bloc est le corps d’une méthode générique, les parameters de type déclarés dans une telle déclaration sont membres de l’espace de déclaration de variable locale du bloc.

C’est une erreur que deux membres d’un espace de déclaration de variable locale aient le même nom. Il s’agit d’une erreur pour un espace de déclaration de variable locale et un espace de déclaration de variable locale nestede contenant des éléments portant le même nom.

[ Note: Ainsi, dans un bloc nested, il n’est pas possible de déclarer une variable locale ou une constante portant le même nom qu’une variable locale ou constante dans un bloc englobant. Il est possible que deux blocs nesteds contiennent des éléments portant le même nom, à condition qu’aucun des deux blocs ne contienne l’autre. note finale ]

Alors

 public void foobar() { if ( foo() ) { int i = 0 ; ... } if ( bar() ) { int i = 0 ; ... } return ; } 

est légal, mais

 public void foobar() { int i = 0 ; if ( foo() ) { int i = 0 ; ... } ... return ; } 

n’est pas légal Personnellement, je trouve la ressortingction plutôt ennuyeuse. Je peux voir un avertissement du compilateur à propos du chevauchement de la scope, mais une erreur de compilation? Trop de ceinture et de bretelles, à mon humble avis. Je pouvais voir la vertu d’une option du compilateur et / ou du pragma (peut-être -pedantic / -practical , #pragma pedantic vs #pragma practical , B^) ).

Je viens de comstackr cela dans GCC à la fois en C et en C ++. Je n’ai reçu aucun message d’erreur, ce qui semble être une syntaxe valide.

Votre question est étiquetée comme .net et c. Cela devrait-il être étiqueté comme c #? Ce langage peut avoir des règles différentes de C.

En C, vous devez mettre toutes les déclarations de variables au tout début d’un bloc. Ils doivent venir directement après l’ouverture { avant toute autre déclaration dans ce bloc.

Donc, ce que vous pouvez faire pour le comstackr est le suivant:

 static void Main() { { int i; } { int i; } } 

Voici votre réponse à partir de la documentation MSDN .NET :

… L’espace de déclaration de la variable locale d’un bloc inclut tous les blocs nesteds. Ainsi, dans un bloc nested, il n’est pas possible de déclarer une variable locale portant le même nom qu’une variable locale dans un bloc englobant.