È comune vedere un _var
nome di variabile in un campo di classe. Cosa significa il carattere di sottolineatura? C'è un riferimento per tutte queste speciali convenzioni di denominazione?
È comune vedere un _var
nome di variabile in un campo di classe. Cosa significa il carattere di sottolineatura? C'è un riferimento per tutte queste speciali convenzioni di denominazione?
Risposte:
Il carattere di sottolineatura è semplicemente una convenzione; niente di più. Come tale, il suo uso è sempre in qualche modo diverso per ogni persona. Ecco come li capisco per le due lingue in questione:
In C ++, un carattere di sottolineatura di solito indica una variabile membro privata.
In C #, di solito vedo che viene utilizzato solo quando si definisce la variabile membro privata sottostante per una proprietà pubblica. Le altre variabili dei membri privati non avrebbero un carattere di sottolineatura. Tuttavia, questo utilizzo è in gran parte al limite con l'avvento delle proprietà automatiche.
Prima:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
Dopo:
public string Name { get; set; }
public string Name { get; private set; }
. È vero, non è perfettamente immutabile, ma è lì.
_var
non è riservato.
È consigliabile NON utilizzare UNDERSCORES prima di qualsiasi nome di variabile o nome di parametro in C ++
I nomi che iniziano con un carattere di sottolineatura o un doppio carattere di sottolineatura sono RISERVATI per gli implementatori C ++. I nomi con un trattino basso sono riservati al funzionamento della libreria.
Se hai letto allo standard di codifica C ++, vedrai che nella prima pagina dice:
"Non ingigantire eccessivamente la denominazione, ma usa una convenzione di denominazione coerente: ci sono solo due cose da fare: a) non usare mai i" nomi subdoli ", quelli che iniziano con un carattere di sottolineatura o che contengono un doppio carattere di sottolineatura;" (p2, standard di codifica C ++, Herb Sutter e Andrei Alexandrescu)
Più specificamente, il progetto di lavoro ISO stabilisce le regole effettive:
Inoltre, alcuni identificatori sono riservati all'uso da parte delle implementazioni C ++ e non devono essere usati diversamente; non è richiesta alcuna diagnostica. (a) Ogni identificatore che contiene un carattere di sottolineatura doppio __ o inizia con un carattere di sottolineatura seguito da una lettera maiuscola è riservato all'implementazione per qualsiasi uso. (b) Ogni identificatore che inizia con un carattere di sottolineatura è riservato all'implementazione per l'uso come nome nello spazio dei nomi globale.
È consigliabile evitare di avviare un simbolo con un carattere di sottolineatura nel caso in cui si vaghi accidentalmente in una delle limitazioni di cui sopra.
Puoi vederlo da solo perché tale uso di caratteri di sottolineatura può essere disastroso durante lo sviluppo di un software:
Prova a compilare un semplice programma helloWorld.cpp come questo:
g++ -E helloWorld.cpp
Vedrai tutto ciò che accade in background. Ecco uno snippet:
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;
}
Puoi vedere quanti nomi iniziano con un doppio trattino basso!
Inoltre, se guardi le funzioni dei membri virtuali, vedrai che * _vptr è il puntatore generato per la tabella virtuale che viene creato automaticamente quando usi una o più funzioni dei membri virtuali nella tua classe! Ma questa è un'altra storia ...
Se usi i caratteri di sottolineatura potresti avere problemi di conflitto e NON AVRAI IDEA che cosa lo sta causando, fino a quando non è troppo tardi.
In realtà la _var
convenzione viene da VB non C # o C ++ (m _, ... è un'altra cosa).
Questo è venuto a superare l'insensibilità del caso di VB nel dichiarare Proprietà.
Ad esempio, tale codice non è possibile in VB perché considera user
e User
come lo stesso identificatore
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
Quindi, per ovviare a questo, alcuni hanno usato una convenzione per aggiungere '_' al campo privato per arrivare in questo modo
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
Poiché molte convenzioni sono per .Net e per mantenere una certa uniformità tra la convenzione C # e VB.NET, stanno usando la stessa.
Ho trovato il riferimento per quello che stavo dicendo: http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices
Custodia per cammello con trattino di punta. In VB.NET, indicare sempre "Protetto" o "Privato", non utilizzare "Dim". L'uso di "m_" è sconsigliato, così come l'uso di un nome di variabile che si differenzia dalla proprietà solo per caso, in particolare con variabili protette in quanto viola la conformità e renderà la tua vita un problema se programmi in VB.NET, come dovrebbe nominare i tuoi membri in modo diverso dalle proprietà accessor / mutator. Di tutti gli elementi qui, il carattere di sottolineatura principale è davvero l'unico controverso. Personalmente lo preferisco al semplice caso di cammello senza sottolineature per le mie variabili private in modo da non dover qualificare i nomi delle variabili con "questo". distinguere dai parametri nei costruttori o altrove dove probabilmente avrò una collisione di denominazione. Con la distinzione tra maiuscole e minuscole di VB.NET, questo è ancora più importante in quanto le proprietà degli accessor avranno di solito lo stesso nome delle variabili dei membri privati ad eccezione del carattere di sottolineatura. Per quanto riguarda m_, si tratta davvero solo di estetica. Io (e molti altri) trovo m_ brutto, in quanto sembra che ci sia un buco nel nome della variabile. È quasi offensivo. Lo usavo sempre in VB6, ma solo perché le variabili non potevano avere un carattere di sottolineatura iniziale. Non potrei essere più felice di vederlo andare via. Microsoft consiglia contro m_ (e il diritto _) anche se hanno fatto entrambi nel loro codice. Inoltre, il prefisso con una "m" dritta è subito chiaro. Naturalmente, poiché codificano principalmente in C #, possono avere membri privati che differiscono solo nel caso dalle proprietà. La gente di VB deve fare qualcos'altro. Anziché provare a presentare casi speciali lingua per lingua, raccomando il carattere di sottolineatura principale per tutte le lingue che lo supporteranno. Se voglio che la mia classe sia completamente conforme a CLS, potrei lasciare il prefisso su qualsiasi variabile membro protetta da C #. In pratica, tuttavia, non mi preoccupo mai di questo perché mantengo private tutte le variabili membro potenzialmente protette e fornisco invece accessori e mutatori protetti. Perché: in poche parole, questa convenzione è semplice (un personaggio), facile da leggere (l'occhio non viene distratto da altri personaggi principali) ed evita con successo la collisione dei nomi con variabili a livello di procedura e proprietà a livello di classe. Proprietà a livello di classe . Consiglio il carattere di sottolineatura principale per tutte le lingue che lo supporteranno. Se voglio che la mia classe sia completamente conforme a CLS, potrei lasciare il prefisso su qualsiasi variabile membro protetta da C #. In pratica, tuttavia, non mi preoccupo mai di questo perché mantengo private tutte le variabili membro potenzialmente protette e fornisco invece accessori e mutatori protetti. Perché: in poche parole, questa convenzione è semplice (un personaggio), facile da leggere (l'occhio non viene distratto da altri personaggi principali) ed evita con successo la collisione dei nomi con variabili a livello di procedura e proprietà a livello di classe. Proprietà a livello di classe . Consiglio il carattere di sottolineatura principale per tutte le lingue che lo supporteranno. Se voglio che la mia classe sia completamente conforme a CLS, potrei lasciare il prefisso su qualsiasi variabile membro protetta da C #. In pratica, tuttavia, non mi preoccupo mai di questo, poiché mantengo private tutte le variabili membro potenzialmente protette e fornisco invece accessori e mutatori protetti. Perché: in poche parole, questa convenzione è semplice (un personaggio), facile da leggere (l'occhio non viene distratto da altri personaggi principali) ed evita con successo la collisione dei nomi con variabili a livello di procedura e proprietà a livello di classe. Proprietà a livello di classe . Non mi preoccupo mai di questo perché mantengo private tutte le variabili membro potenzialmente protette e fornisco invece accessori e mutatori protetti. Perché: in poche parole, questa convenzione è semplice (un personaggio), facile da leggere (l'occhio non viene distratto da altri personaggi principali) ed evita con successo la collisione dei nomi con variabili a livello di procedura e proprietà a livello di classe. Proprietà a livello di classe . Non mi preoccupo mai di questo perché mantengo private tutte le variabili membro potenzialmente protette e fornisco invece accessori e mutatori protetti. Perché: in poche parole, questa convenzione è semplice (un personaggio), facile da leggere (l'occhio non viene distratto da altri personaggi principali) ed evita con successo la collisione dei nomi con variabili a livello di procedura e proprietà a livello di classe. Proprietà a livello di classe .
Il primo commentatore (R Samuel Klatchko) ha fatto riferimento: Quali sono le regole sull'uso di un trattino basso in un identificatore C ++? che risponde alla domanda sul carattere di sottolineatura in C ++. In generale, non è necessario utilizzare un carattere di sottolineatura iniziale, poiché è riservato all'implementatore del compilatore. Il codice con cui stai vedendo _var
è probabilmente un codice legacy o un codice scritto da qualcuno che è cresciuto usando il vecchio sistema di denominazione che non si è accigliato con i caratteri di sottolineatura principali.
Come indicato da altre risposte, era usato in C ++ per identificare le variabili dei membri della classe. Tuttavia, non ha alcun significato speciale per quanto riguarda decoratori o sintassi. Quindi, se si desidera utilizzarlo, verrà compilato.
Lascio la discussione in C # ad altri.
_var non ha alcun significato e serve solo allo scopo di semplificare la distinzione che la variabile è una variabile membro privata.
In C ++, l'uso della convenzione _var non è corretto, poiché esistono regole che governano l'uso del trattino basso davanti a un identificatore. _var è riservato come identificatore globale, mentre _Var (trattino basso + lettera maiuscola) è sempre riservato. Questo è il motivo per cui in C ++ vedrai invece persone che usano la convenzione var_.
Puoi creare le tue linee guida per la codifica. Basta scrivere una documentazione chiara per il resto della squadra.
L'uso di _field aiuta Intelilsense a filtrare tutte le variabili di classe semplicemente digitando _.
Di solito seguo le Linee guida di Brad Adams , ma mi consiglia di non utilizzare il carattere di sottolineatura.
Lo standard di denominazione Microsoft per C #, dice variabili e parametri devono utilizzare il modulo caso cammello inferiore IE: paramName
. Lo standard prevede inoltre campi per seguire la stessa forma, ma questo può portare a codice chiaro così tante squadre richiedono un prefisso di sottolineatura per migliorare la chiarezza IE: _fieldName
.
Con C #, le Linee guida per la progettazione di Microsoft Framework suggeriscono di non utilizzare il carattere di sottolineatura per i membri pubblici . Per i membri privati , i caratteri di sottolineatura sono OK da usare. In effetti, Jeffrey Richter (spesso citato nelle linee guida) usa un m_ per esempio e un "s_" per membri statici privati.
Personalmente, uso solo _ per contrassegnare i miei membri privati. "m_" e "s_" si avvicinano alla notazione ungherese che non è solo disapprovata in .NET, ma può essere piuttosto dettagliata e trovo che le classi con molti membri siano difficili da eseguire una rapida occhiata in ordine alfabetico (immagina 10 variabili tutte che iniziano con m_) .
Uso il nome _var per le variabili membro delle mie classi. Ci sono 2 motivi principali per cui lo faccio:
1) Mi aiuta a tenere traccia delle variabili di classe e delle variabili di funzione locali quando leggo il mio codice in seguito.
2) Aiuta Intellisense (o altro sistema di completamento del codice) quando cerco una variabile di classe. Il solo fatto di conoscere il primo carattere è utile per filtrare l'elenco delle variabili e dei metodi disponibili.
Per quanto riguarda i linguaggi C e C ++, non esiste un significato speciale per un carattere di sottolineatura nel nome (inizio, metà o fine). È solo un carattere di nome variabile valido. Le "convenzioni" provengono da pratiche di codifica all'interno di una comunità di codifica.
Come già indicato da vari esempi sopra, _ all'inizio può significare membri privati o protetti di una classe in C ++.
Vorrei solo dare un po 'di storia che può essere divertente curiosità. In UNIX se si dispone di una funzione di libreria C centrale e di un back-end del kernel in cui si desidera esporre la funzione del kernel allo spazio utente, _ è bloccato di fronte allo stub della funzione che chiama direttamente la funzione del kernel senza fare altro. L'esempio più famoso e familiare di questo è exit () vs _exit () nei kernel di tipo BSD e SysV: lì, exit () fa cose nello spazio utente prima di chiamare il servizio di uscita del kernel, mentre _exit si limita al servizio di uscita del kernel.
Quindi _ è stato usato per cose "locali" in questo caso locale essendo macchina locale. In genere _functions () non erano portatili. In questo non dovresti aspettarti lo stesso comportamento su varie piattaforme.
Ora come per _ nei nomi delle variabili, come ad esempio
int _foo;
Bene psicologicamente, un _ è una cosa strana da digitare all'inizio. Quindi, se si desidera creare un nome di variabile che avrebbe una minore possibilità di scontro con qualcos'altro, in particolare quando si ha a che fare con sostituzioni pre-processore si considera l'uso di _.
Il mio consiglio di base sarebbe di seguire sempre le convenzioni della tua comunità di programmazione, in modo da poter collaborare in modo più efficace.
A molte persone piace avere campi privati con il prefisso. È solo una convenzione di denominazione.
Le convenzioni di denominazione "ufficiali" di C # prescrivono nomi minuscoli semplici (senza trattino basso) per i campi privati.
Non sono a conoscenza delle convenzioni standard per il C ++, sebbene i caratteri di sottolineatura siano ampiamente utilizzati.
È solo una convenzione che alcuni programmatori usano per chiarire quando manipoli un membro della classe o qualche altro tipo di variabile (parametri, locale alla funzione, ecc.). Un'altra convenzione ampiamente utilizzata per le variabili membro è il prefisso del nome con "m_".
Comunque, queste sono solo convenzioni e non troverai un'unica fonte per tutte. Sono una questione di stile e ogni team di programmazione, progetto o azienda ha il suo (o addirittura non ne ha).
C'è un motivo pienamente legittimo per usarlo in C #: se il codice deve essere estendibile anche da VB.NET. (Altrimenti, non lo farei.)
Poiché VB.NET non fa distinzione tra maiuscole e minuscole, non esiste un modo semplice per accedere al field
membro protetto in questo codice:
public class CSharpClass
{
protected int field;
public int Field { get { return field; } }
}
Ad esempio, questo accederà al getter della proprietà, non al campo:
Public Class VBClass
Inherits CSharpClass
Function Test() As Integer
Return Field
End Function
End Class
Cavolo, non riesco nemmeno a scrivere field
in minuscolo - VS 2010 continua a correggerlo.
Per renderlo facilmente accessibile alle classi derivate in VB.NET, è necessario elaborare un'altra convenzione di denominazione. Il prefisso di un trattino basso è probabilmente il meno invadente e il più "storicamente accettato".
Vecchia domanda, nuova risposta (C #).
Un altro uso di caratteri di sottolineatura per C # è con DI DI NET NET (iniezione di dipendenza). Le readonly
variabili private di una classe assegnate all'interfaccia iniettata durante la costruzione dovrebbero iniziare con un trattino basso. Immagino sia un dibattito se usare il carattere di sottolineatura per ogni membro privato di una classe (sebbene la stessa Microsoft lo segua) ma questo è certo.
private readonly ILogger<MyDependency> _logger;
public MyDependency(ILogger<MyDependency> logger)
{
_logger = logger;
}
Una convenzione di denominazione come questa è utile quando leggi il codice, in particolare il codice che non è il tuo. Una forte convenzione di denominazione aiuta a indicare dove viene definito un determinato membro, che tipo di membro è, ecc. La maggior parte dei team di sviluppo adotta una semplice convenzione di denominazione e semplicemente prefigura i campi dei membri con un carattere di sottolineatura ( _fieldName
). In passato, ho usato la seguente convenzione di denominazione per C # (che si basa sulle convenzioni di Microsofts per il codice di .NET framework, che può essere visto con Reflector):
Campo istanza: m_fieldName
Campo statico: s_fieldName Membro
pubblico / protetto / interno: PascalCasedName ()
Membro privato: camelCasedName ()
Questo aiuta le persone a comprendere la struttura, l'uso, l'accessibilità e la posizione dei membri quando leggono il codice sconosciuto molto rapidamente.