Pourquoi C # permet blocs de code sans une déclaration précédente (par exemple if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Pourquoi C # permet blocs de code sans une déclaration précédente (par exemple if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Réponses:
Dans le contexte que vous donnez, il n'y a aucune signification. L'écriture d'une chaîne constante sur la console fonctionnera de la même manière partout dans le déroulement du programme. 1
Au lieu de cela, vous les utilisez généralement pour restreindre la portée de certaines variables locales. Ceci est développé ici et ici . Regardez la réponse de João Angelo et la réponse de Chris Wallis pour des exemples de brefs. Je pense que la même chose s'applique à certains autres langages avec une syntaxe de style C, non pas qu'ils seraient pertinents pour cette question.
1 À moins, bien sûr, vous décidez d'essayer d'être drôle et de créer votre propre Console
classe, avec une Write()
méthode qui fait quelque chose de tout à fait inattendu.
out
paramètre à une implémentation d'interface écrite dans un autre langage, et cette implémentation lit la variable avant de l'écrire.
Le { ... }
a au moins pour effet secondaire d'introduire une nouvelle portée pour les variables locales.
J'ai tendance à les utiliser dans des switch
déclarations pour fournir une portée différente pour chaque cas et me permettant ainsi de définir une variable locale avec le même nom à l'emplacement le plus proche possible de leur utilisation et pour indiquer également qu'elles ne sont valables qu'au niveau du cas.
{}
pour garder ces badges d'or à venir ... :)
Ce n'est pas tant une fonctionnalité de C # qu'un effet secondaire logique de nombreux langages de syntaxe C qui utilisent des accolades pour définir la portée .
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 tombe hors de portée dans le premier bloc et est défini à nouveau dans le suivant:
{
{
int i = 0;
}
{
int i = 0;
}
}
Cela n'est pas autorisé car i est tombé hors de portée et n'est plus visible dans la portée externe:
{
{
int i = 0;
}
i = 1;
}
Ainsi de suite.
{}
appelées parenthèses?
One of two marks of the form [ ] or ( ), and in mathematical use also {}, used for enclosing a word or number of words, a portion of a mathematical formula, or the like, so as to separate it from the context;
Dans tous les cas, ce ne sont pas des parenthèses, mais «crochet bouclé» semble correct.
Je considère {}
comme une déclaration pouvant contenir plusieurs déclarations.
Considérez une instruction if qui existe à partir d'une expression booléenne suivie d' une instruction. Cela fonctionnerait:
if (true) Console.Write("FooBar");
Cela fonctionnerait également:
if (true)
{
Console.Write("Foo");
Console.Write("Bar");
}
Si je ne me trompe pas, cela s'appelle une instruction de bloc.
Puisque {}
peut contenir d'autres instructions, il peut également en contenir d'autres {}
. La portée d'une variable est définie par son parent {}
(instruction de bloc).
Le point que j'essaie de faire valoir est que ce {}
n'est qu'une déclaration, donc cela ne nécessite pas de si ou quoi que ce soit ...
La règle générale dans les langages de syntaxe C est que "tout ce qui se trouve entre { }
doit être traité comme une seule instruction, et il peut aller partout où une seule instruction le peut":
if
.for
, while
ou do
.À toutes fins utiles, c'est comme la grammaire de la langue incluait ceci:
<statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>
Autrement dit, "une instruction peut être composée de (diverses choses) ou d'une accolade ouvrante, suivie d'une liste d'instructions (qui peut inclure une ou plusieurs instructions), suivie d'une accolade fermée". IE "un { }
bloc peut remplacer n'importe quelle instruction, n'importe où". Y compris au milieu du code.
Ne pas autoriser un { }
bloc à un endroit 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 autorisés parce que C l'a fait.
On pourrait dire que tout se résume au fait que la conception du langage de programme américain (basé sur C) a gagné plutôt que la conception du langage de programme européen ( basé sur Modula-2 ).
(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 instructions précédentes. La question "pourquoi" pourrait également être interprétée comme "quels seraient les avantages possibles de ce concept?"
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érez 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 plus élégamment en utilisant des méthodes pour chaque niveau de structure. Mais là encore, gardez à l'esprit que des choses comme les semeurs d'é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 du code représente la structure "du monde réel" des objets, facilitant ainsi la compréhension, la maintenance et l'extension des autres développeurs.