Il est courant de voir un _var
nom de variable dans un champ de classe. Que signifie le trait de soulignement? Existe-t-il une référence pour toutes ces conventions de dénomination spéciales?
Il est courant de voir un _var
nom de variable dans un champ de classe. Que signifie le trait de soulignement? Existe-t-il une référence pour toutes ces conventions de dénomination spéciales?
Réponses:
Le trait de soulignement est simplement une convention; rien de plus. En tant que tel, son utilisation est toujours quelque peu différente pour chaque personne. Voici comment je les comprends pour les deux langues en question:
En C ++, un trait de soulignement indique généralement une variable de membre privé.
En C #, je le vois généralement utilisé uniquement lors de la définition de la variable de membre privé sous-jacente pour une propriété publique. Les autres variables de membre privé n'auraient pas de trait de soulignement. Cependant, cet usage a largement disparu avec l'avènement des propriétés automatiques.
Avant:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
Après:
public string Name { get; set; }
public string Name { get; private set; }
. Certes, ce n'est pas parfaitement immuable, mais c'est là.
_var
n'est pas réservé.
Il est recommandé de NE PAS utiliser UNDERSCORES avant tout nom de variable ou nom de paramètre en C ++
Les noms commençant par un trait de soulignement ou un double trait de soulignement sont RÉSERVÉS aux implémenteurs C ++. Les noms avec un trait de soulignement sont réservés au fonctionnement de la bibliothèque.
Si vous avez une lecture de la norme de codage C ++, vous verrez que dans la toute première page, il est dit:
"Ne pas trop légiférer sur la dénomination, mais utilisez une convention de dénomination cohérente: il n'y a que deux choses à faire: a) ne jamais utiliser de" noms sournois ", ceux qui commencent par un trait de soulignement ou qui contiennent un double trait de soulignement;" (p2, normes de codage C ++, Herb Sutter et Andrei Alexandrescu)
Plus précisément, le projet de travail de l' ISO énonce les règles actuelles:
De plus, certains identificateurs sont réservés à l'usage des implémentations C ++ et ne doivent pas être utilisés autrement; aucun diagnostic n'est requis. (a) Chaque identifiant contenant un double trait de soulignement __ ou commençant par un trait de soulignement suivi d'une lettre majuscule est réservé à l'implémentation pour toute utilisation. (b) Chaque identificateur qui commence par un trait de soulignement est réservé à l'implémentation pour être utilisé comme nom dans l'espace de noms global.
Il est recommandé d'éviter de commencer un symbole par un trait de soulignement au cas où vous vous retrouveriez accidentellement dans l'une des limitations ci-dessus.
Vous pouvez voir par vous-même pourquoi une telle utilisation de traits de soulignement peut être désastreuse lors du développement d'un logiciel:
Essayez de compiler un simple programme helloWorld.cpp comme ceci:
g++ -E helloWorld.cpp
Vous verrez tout ce qui se passe en arrière-plan. Voici un extrait:
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
try
{
__streambuf_type* __sb = this->rdbuf();
if (__sb)
{
if (__sb->pubsync() == -1)
__err |= ios_base::badbit;
else
__ret = 0;
}
Vous pouvez voir combien de noms commencent par un double tiret bas!
De plus, si vous regardez les fonctions membres virtuelles, vous verrez que * _vptr est le pointeur généré pour la table virtuelle qui est automatiquement créée lorsque vous utilisez une ou plusieurs fonctions membres virtuelles dans votre classe! Mais c'est une autre histoire ...
Si vous utilisez des traits de soulignement, vous pourriez avoir des problèmes de conflit et vous n'aurez AUCUNE IDÉE de la cause, jusqu'à ce qu'il soit trop tard.
En fait, la _var
convention vient de VB et non de C # ou C ++ (m _, ... est autre chose).
Cela a permis de surmonter l'insensibilité à la casse de VB lors de la déclaration de propriétés.
Par exemple, un tel code n'est pas possible dans VB car il considère user
et User
comme le même identifiant
Private user As String
Public Property User As String
Get
Return user
End Get
Set(ByVal Value As String)
user = value
End Set
End Property
Donc pour surmonter cela, certains ont utilisé une convention pour ajouter '_' au champ privé pour venir comme ça
Private _user As String
Public Property User As String
Get
Return _user
End Get
Set(ByVal Value As String)
_user = value
End Set
End Property
Étant donné que de nombreuses conventions sont pour .Net et pour conserver une certaine uniformité entre les conventions C # et VB.NET, elles utilisent la même.
J'ai trouvé la référence de ce que je disais: http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices
Étui de chameau avec soulignement principal. Dans VB.NET, indiquez toujours «Protected» ou «Private», n'utilisez pas «Dim». L'utilisation de "m_" est déconseillée, tout comme l'utilisation d'un nom de variable qui diffère de la propriété uniquement par casse, en particulier avec des variables protégées car cela enfreint la conformité, et vous rendra la vie difficile si vous programmez dans VB.NET, comme vous devrait nommer vos membres différemment des propriétés de l'accesseur / mutateur. De tous les éléments ici, le trait de soulignement principal est vraiment le seul controversé. Personnellement, je préfère cela au cas de chameau sans trait de soulignement pour mes variables privées afin que je n'ai pas à qualifier les noms de variables avec «ceci». pour distinguer des paramètres dans les constructeurs ou ailleurs où j'aurai probablement une collision de noms. Avec l'insensibilité à la casse de VB.NET, cela est d'autant plus important que vos propriétés d'accesseur auront généralement le même nom que vos variables de membre privé à l'exception du trait de soulignement. Pour ce qui est de m_, il ne s'agit en réalité que d'esthétique. Moi (et beaucoup d'autres) trouve m_ laid, car il semble qu'il y ait un trou dans le nom de la variable. C'est presque offensant. J'avais l'habitude de l'utiliser tout le temps dans VB6, mais c'était uniquement parce que les variables ne pouvaient pas avoir de trait de soulignement principal. Je ne pourrais pas être plus heureux de le voir disparaître. Microsoft déconseille le m_ (et le simple _) même s'ils ont fait les deux dans leur code. En outre, le préfixe avec un "m" droit est tout à fait correct. Bien sûr, comme ils codent principalement en C #, ils peuvent avoir des membres privés qui ne diffèrent que par le cas des propriétés. Les gens de VB doivent faire autre chose. Plutôt que d'essayer de proposer des cas spéciaux langue par langue, je recommande le trait de soulignement principal pour toutes les langues qui le prendront en charge. Si je veux que ma classe soit entièrement compatible CLS, je peux laisser le préfixe sur toutes les variables membres protégées C #. Dans la pratique, cependant, je ne m'inquiète jamais à ce sujet car je garde toutes les variables membres potentiellement protégées privées et fournit à la place des accesseurs et des mutateurs protégés. Pourquoi: En un mot, cette convention est simple (un caractère), facile à lire (votre œil n'est pas distrait par les autres caractères principaux) et évite avec succès les collisions de noms avec les variables au niveau de la procédure et les propriétés au niveau de la classe. . Je recommande le trait de soulignement principal pour toutes les langues qui le prendront en charge. Si je veux que ma classe soit entièrement compatible CLS, je peux laisser le préfixe sur toutes les variables membres protégées C #. Dans la pratique, cependant, je ne m'inquiète jamais à ce sujet car je garde toutes les variables membres potentiellement protégées privées et fournit à la place des accesseurs et des mutateurs protégés. Pourquoi: En un mot, cette convention est simple (un caractère), facile à lire (votre œil n'est pas distrait par les autres caractères principaux) et évite avec succès les collisions de noms avec les variables au niveau de la procédure et les propriétés au niveau de la classe. . Je recommande le trait de soulignement principal pour toutes les langues qui le prendront en charge. Si je veux que ma classe soit entièrement compatible CLS, je peux laisser le préfixe sur toutes les variables membres protégées C #. Dans la pratique, cependant, je ne m'inquiète jamais à ce sujet car je garde toutes les variables membres potentiellement protégées privées et fournit à la place des accesseurs et des mutateurs protégés. Pourquoi: En un mot, cette convention est simple (un caractère), facile à lire (votre œil n'est pas distrait par les autres caractères principaux) et évite avec succès les collisions de noms avec les variables au niveau de la procédure et les propriétés au niveau de la classe. . Je ne m'inquiète jamais à ce sujet car je garde toutes les variables de membre potentiellement protégées privées et fournit à la place des accesseurs et des mutateurs protégés. Pourquoi: En un mot, cette convention est simple (un caractère), facile à lire (votre œil n'est pas distrait par les autres caractères principaux) et évite avec succès les collisions de noms avec les variables au niveau de la procédure et les propriétés au niveau de la classe. . Je ne m'inquiète jamais à ce sujet car je garde toutes les variables de membre potentiellement protégées privées et fournit à la place des accesseurs et des mutateurs protégés. Pourquoi: En un mot, cette convention est simple (un caractère), facile à lire (votre œil n'est pas distrait par les autres caractères de tête) et évite avec succès les collisions de noms avec les variables de niveau procédure et les propriétés de niveau classe. .
Le premier commentateur (R Samuel Klatchko) a référencé: Quelles sont les règles d'utilisation d'un trait de soulignement dans un identifiant C ++? qui répond à la question sur le trait de soulignement en C ++. En général, vous n'êtes pas censé utiliser un trait de soulignement au début, car il est réservé à l'implémenteur de votre compilateur. Le code que vous voyez _var
est probablement soit du code hérité, soit du code écrit par quelqu'un qui a grandi en utilisant l'ancien système de dénomination qui n'a pas froncé les sourcils sur les principaux traits de soulignement.
Comme d'autres réponses l'indiquent, il était utilisé en C ++ pour identifier les variables de membre de classe. Cependant, cela n'a pas de signification particulière en ce qui concerne les décorateurs ou la syntaxe. Donc, si vous voulez l'utiliser, il se compilera.
Je vais laisser la discussion C # aux autres.
_var n'a aucune signification et sert uniquement à faciliter la distinction entre le fait que la variable est une variable de membre privé.
En C ++, utiliser la convention _var est une mauvaise forme, car il existe des règles régissant l'utilisation du trait de soulignement devant un identificateur. _var est réservé comme identifiant global, tandis que _Var (trait de soulignement + majuscule) est réservé à tout moment. C'est pourquoi en C ++, vous verrez des gens utiliser la convention var_ à la place.
Vous pouvez créer vos propres directives de codage. Rédigez simplement une documentation claire pour le reste de l'équipe.
L'utilisation de _field aide Intelilsense à filtrer toutes les variables de classe en tapant simplement _.
Je suis généralement les directives de Brad Adams , mais il recommande de ne pas utiliser de soulignement.
La norme nommant Microsoft C # indique les variables et les paramètres doivent utiliser la forme inférieure de cas de chameau IE: paramName
. La norme exige également des champs à suivre la même forme , mais cela peut conduire à un code peu clair tant d'équipes appellent à un préfixe de soulignement pour améliorer la clarté IE: _fieldName
.
Avec C #, les directives de conception de Microsoft Framework suggèrent de ne pas utiliser le caractère de soulignement pour les membres publics . Pour les membres privés , les traits de soulignement peuvent être utilisés. En fait, Jeffrey Richter (souvent cité dans les directives) utilise un m_ par exemple et un «s_» pour les membres statiques privés.
Personnellement, j'utilise juste _ pour marquer mes membres privés. "m_" et "s_" frôlent la notation hongroise qui n'est pas seulement désapprouvée dans .NET, mais peut être assez verbeuse et je trouve que les classes avec de nombreux membres ont du mal à faire un scan rapide des yeux par ordre alphabétique (imaginez 10 variables commençant toutes par m_) .
J'utilise la dénomination _var pour les variables membres de mes classes. Il y a 2 raisons principales pour lesquelles je fais:
1) Cela m'aide à garder une trace des variables de classe et des variables de fonction locales lorsque je lis mon code plus tard.
2) Cela aide Intellisense (ou tout autre système de complétion de code) lorsque je recherche une variable de classe. Le simple fait de connaître le premier caractère est utile pour filtrer la liste des variables et méthodes disponibles.
En ce qui concerne les langages C et C ++, il n'y a pas de signification particulière à un trait de soulignement dans le nom (début, milieu ou fin). C'est juste un caractère de nom de variable valide. Les «conventions» proviennent de pratiques de codage au sein d'une communauté de codage.
Comme déjà indiqué par divers exemples ci-dessus, _ au début peut signifier des membres privés ou protégés d'une classe en C ++.
Permettez-moi de vous donner une histoire qui pourrait être des anecdotes amusantes. Sous UNIX, si vous avez une fonction de bibliothèque de base C et un back-end du noyau où vous voulez également exposer la fonction du noyau à l'espace utilisateur, le _ est bloqué devant le stub de fonction qui appelle directement la fonction du noyau sans rien faire d'autre. L'exemple le plus célèbre et le plus familier de ceci est exit () vs _exit () sous les noyaux de type BSD et SysV: là, exit () fait des choses sur l'espace utilisateur avant d'appeler le service de sortie du noyau, alors que _exit correspond simplement au service de sortie du noyau.
Donc _ a été utilisé pour les trucs "locaux" dans ce cas, local étant localement à la machine. En général, les fonctions _functions () n'étaient pas portables. En cela, vous ne devriez pas vous attendre au même comportement sur différentes plates-formes.
Maintenant, comme pour _ dans les noms de variables, tels que
int _foo;
Eh bien psychologiquement, un _ est une chose étrange à taper au début. Donc, si vous voulez créer un nom de variable qui aurait moins de chance de heurter quelque chose d'autre, PARTICULIÈREMENT lorsque vous traitez avec des substitutions pré-processeurs, vous voulez considérer les utilisations de _.
Mon conseil de base serait de toujours suivre la convention de votre communauté de codage, afin que vous puissiez collaborer plus efficacement.
Beaucoup de gens aiment que les champs privés soient précédés d'un trait de soulignement. C'est juste une convention de dénomination.
Les conventions de dénomination «officielles» de C # prescrivent des noms simples en minuscules (sans trait de soulignement) pour les champs privés.
Je ne connais pas les conventions standard pour C ++, bien que les traits de soulignement soient très largement utilisés.
C'est juste une convention que certains programmeurs utilisent pour préciser lorsque vous manipulez un membre de la classe ou un autre type de variable (paramètres, local de la fonction, etc.). Une autre convention qui est également largement utilisée pour les variables membres est le préfixe du nom avec «m_».
Quoi qu'il en soit, ce ne sont que des conventions et vous ne trouverez pas une seule source pour toutes. C'est une question de style et chaque équipe de programmation, projet ou entreprise a le sien (ou même n'en a pas).
Il y a une raison tout à fait légitime de l'utiliser en C #: si le code doit également être extensible à partir de VB.NET. (Sinon, je ne le ferais pas.)
Puisque VB.NET est insensible à la casse, il n'y a pas de moyen simple d'accéder au field
membre protégé dans ce code:
public class CSharpClass
{
protected int field;
public int Field { get { return field; } }
}
Par exemple, cela accédera au getter de propriété, pas au champ:
Public Class VBClass
Inherits CSharpClass
Function Test() As Integer
Return Field
End Function
End Class
Heck, je ne peux même pas écrire field
en minuscules - VS 2010 ne cesse de le corriger.
Afin de le rendre facilement accessible aux classes dérivées dans VB.NET, il faut trouver une autre convention de dénomination. Le préfixe d'un trait de soulignement est probablement le moins intrusif et le plus "historiquement accepté" d'entre eux.
Ancienne question, nouvelle réponse (C #).
Une autre utilisation des traits de soulignement pour C # est avec la DI d'ASP NET Core (injection de dépendances). Les readonly
variables privées d'une classe qui ont été affectées à l'interface injectée pendant la construction doivent commencer par un trait de soulignement. Je suppose que c'est un débat pour savoir s'il faut utiliser le trait de soulignement pour chaque membre privé d'une classe (bien que Microsoft lui-même le suive), mais celui-ci est certain.
private readonly ILogger<MyDependency> _logger;
public MyDependency(ILogger<MyDependency> logger)
{
_logger = logger;
}
Une convention de dénomination comme celle-ci est utile lorsque vous lisez du code, en particulier du code qui ne vous appartient pas. Une convention de dénomination forte permet d'indiquer où un membre particulier est défini, de quel type de membre il s'agit, etc. La plupart des équipes de développement adoptent une convention de dénomination simple et préfixent simplement les champs de membre avec un trait de soulignement ( _fieldName
). Dans le passé, j'ai utilisé la convention de dénomination suivante pour C # (qui est basée sur les conventions Microsofts pour le code du framework .NET, qui peut être vue avec Reflector):
Champ d'instance: m_fieldName
Champ statique: s_fieldName Membre
public / protégé / interne: PascalCasedName ()
Membre privé: camelCasedName ()
Cela aide les gens à comprendre la structure, l'utilisation, l'accessibilité et l'emplacement des membres lorsqu'ils lisent très rapidement du code inconnu.