Pourquoi C # autorise-t-il les blocs de code sans instruction précédente (par exemple, if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Dans le contexte que vous donnez, cela n’a aucune signification. L’écriture d’une chaîne constante sur la console fonctionnera de la même manière n’importe où dans le déroulement du programme.1
Au lieu de cela, vous les utilisez généralement pour limiter la portée de certaines variables locales. Ceci est plus en détail ici et ici . Regardez la réponse de João Angelo et la réponse de Chris Wallis pour de brefs exemples. Je pense que la même chose s’applique à certains autres langages avec une syntaxe de style C également, même s’ils ne sont pas pertinents pour cette question.
1À moins, bien sûr, que vous décidiez d'essayer d'être drôle et de créer votre propre classe Console
, avec une méthode Write()
qui effectue quelque chose de totalement inattendu.
Le { ... }
a au moins l'effet secondaire d'introduire une nouvelle portée pour les variables locales.
J'ai tendance à les utiliser dans des instructions switch
pour fournir une étendue différente pour chaque cas, me permettant ainsi de définir une variable locale portant le même nom à l'emplacement le plus proche possible de leur utilisation et d'indiquer également qu'elles ne sont valides qu'au niveau de l'affaire. .
Ce n'est pas tant une fonction feature de C # qu'un effet secondaire logique de nombreux langages de syntaxe C qui utilisent des accolades pour define scope .
Dans votre exemple, les accolades n'ont aucun effet, mais dans le code suivant, elles définissent la portée, et donc la visibilité, d'une variable:
Ceci est autorisé car i sort du domaine dans le premier bloc et est défini à nouveau dans le suivant:
{
{
int i = 0;
}
{
int i = 0;
}
}
Ceci n'est pas autorisé car je suis tombé hors de la portée et n'est plus visible dans la portée extérieure:
{
{
int i = 0;
}
i = 1;
}
Ainsi de suite.
Je considère {}
comme une déclaration pouvant contenir plusieurs déclarations.
Considérons une instruction if qui existe à partir d'une expression booléenne suivie de one statement. Cela fonctionnerait:
if (true) Console.Write("FooBar");
Cela fonctionnerait aussi bien:
if (true)
{
Console.Write("Foo");
Console.Write("Bar");
}
Si je ne me trompe pas, cela s'appelle une déclaration de bloc.
Puisque {}
peut contenir d'autres instructions, il peut également contenir d'autres {}
. La portée d'une variable est définie par son parent {}
(instruction de bloc).
Ce que j'essaie de dire, c'est que {}
est juste une déclaration, de sorte qu'elle n'exige pas de if ou quoi que ce soit ...
La règle générale dans les langages de syntaxe C est la suivante: "tout ce qui est entre { }
devrait être traité comme une seule instruction et il peut aller partout où une seule instruction le pourrait":
if
.for
, while
ou do
.À toutes fins utiles, c'est comme la grammaire de langue inclus ceci:
<statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>
C'est-à-dire "une déclaration peut être composée de (choses diverses) ou d'une attelle d'ouverture suivie d'une liste d'instructions (pouvant inclure une ou plusieurs déclarations), suivie d'une accolade fermée". C'EST À DIRE. "un bloc { }
peut remplacer n'importe quelle instruction, n'importe où". Y compris au milieu du code.
Ne pas autoriser un bloc { }
partout où une seule instruction peut aller aurait en fait rendu la définition du langage plus complexe .
Parce que C++ (et Java) autorisait les blocs de code sans instruction précédente.
C++ les a permis parce que C l'a fait.
On pourrait dire que tout se résume au fait que le design basé sur la langue de programmation américaine (basé sur C) a été remporté plutôt que sur le design basé sur une langue de programmation européenne ( Modula-2 based).
(Les instructions de contrôle agissent sur une seule instruction, les instructions peuvent être des groupes pour créer de nouvelles instructions)
// if (a == b)
// if (a != b)
{
// do something
}
Vous avez demandé "pourquoi" C # autorise les blocs de code sans instruction précédente. La question "pourquoi" pourrait également être interprétée comme "quels seraient les avantages possibles de cette construction?"
Personnellement, j'utilise des blocs de code sans instruction en C # où la lisibilité est grandement améliorée pour les autres développeurs, tout en gardant à l'esprit que le bloc de code limite la portée des variables locales. Par exemple, considérons l'extrait de code suivant, qui est beaucoup plus facile à lire grâce aux blocs de code supplémentaires:
OrgUnit world = new OrgUnit() { Name = "World" };
{
OrgUnit europe = new OrgUnit() { Name = "Europe" };
world.SubUnits.Add(europe);
{
OrgUnit germany = new OrgUnit() { Name = "Germany" };
europe.SubUnits.Add(germany);
//...etc.
}
}
//...commit structure to DB here
Je suis conscient que cela pourrait être résolu de manière plus élégante en utilisant des méthodes pour chaque niveau de structure. Mais encore une fois, gardez à l'esprit que des éléments tels que les échantillons de données doivent généralement être rapides.
Ainsi, même si le code ci-dessus est exécuté de manière linéaire, la structure de code représente la structure "réelle" des objets, ce qui facilite la compréhension, la maintenance et l'extension des autres développeurs.
1 Parce que ... Il conserve la zone de définition de l'instruction.
{
{
// Here this 'i' is we can use for this scope only and out side of this scope we can't get this 'i' variable.
int i = 0;
}
{
int i = 0;
}
}