Es común ver un _var
nombre de variable en un campo de clase. ¿Qué significa el guión bajo? ¿Hay alguna referencia para todas estas convenciones de nombres especiales?
Es común ver un _var
nombre de variable en un campo de clase. ¿Qué significa el guión bajo? ¿Hay alguna referencia para todas estas convenciones de nombres especiales?
Respuestas:
El guión bajo es simplemente una convención; nada mas. Como tal, su uso siempre es algo diferente para cada persona. Así es como los entiendo para los dos idiomas en cuestión:
En C ++, un guión bajo generalmente indica una variable miembro privada.
En C #, generalmente veo que se usa solo cuando se define la variable de miembro privado subyacente para una propiedad pública. Otras variables de miembros privados no tendrían un guión bajo. Sin embargo, este uso se ha desvanecido con el advenimiento de las propiedades automáticas.
Antes de:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
Después:
public string Name { get; set; }
public string Name { get; private set; }
. Es cierto que no es perfectamente inmutable, pero está ahí.
_var
No esta reservado.
Es una buena práctica NO usar UNDERSCORES antes de cualquier nombre de variable o nombre de parámetro en C ++
Los nombres que comienzan con un guión bajo o un guión bajo doble están RESERVADOS para los implementadores de C ++. Los nombres con un guión bajo están reservados para que la biblioteca funcione.
Si tiene una lectura en el Estándar de codificación C ++, verá que en la primera página dice:
"No sobrelegislate los nombres, pero use una convención de nomenclatura consistente: solo hay dos cosas que debe hacer: a) nunca use" nombres poco claros ", los que comienzan con un guión bajo o que contienen un guión bajo doble"; (p2, estándares de codificación C ++, Herb Sutter y Andrei Alexandrescu)
Más específicamente, el borrador de trabajo de ISO establece las reglas reales:
Además, algunos identificadores están reservados para su uso en implementaciones de C ++ y no se utilizarán de otra manera; No se requiere diagnóstico. (a) Cada identificador que contenga un guión bajo doble __ o comience con un guión bajo seguido de una letra mayúscula está reservado a la implementación para cualquier uso. (b) Cada identificador que comienza con un guión bajo está reservado a la implementación para su uso como nombre en el espacio de nombres global.
Es una buena práctica evitar comenzar un símbolo con un guión bajo en caso de que accidentalmente pase por una de las limitaciones anteriores.
Puede verlo usted mismo por qué el uso de guiones bajos puede ser desastroso al desarrollar un software:
Intente compilar un programa simple helloWorld.cpp como este:
g++ -E helloWorld.cpp
Verá todo lo que sucede en el fondo. Aquí hay un fragmento:
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;
}
¡Puedes ver cuántos nombres comienzan con doble guión bajo!
Además, si observa las funciones de miembros virtuales, verá que * _vptr es el puntero generado para la tabla virtual que se crea automáticamente cuando utiliza una o más funciones de miembros virtuales en su clase. Pero esa es otra historia ...
Si usa guiones bajos, podría tener problemas de conflicto y NO TENDRÁ IDEA lo que lo está causando, hasta que sea demasiado tarde.
En realidad, la _var
convención proviene de VB, no de C # o C ++ (m _, ... es otra cosa).
Esto llegó a superar la insensibilidad de VB al declarar Propiedades.
Por ejemplo, dicho código no es posible en VB porque lo considera user
y User
como el mismo identificador
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
Entonces, para superar esto, algunos usaron una convención para agregar '_' al campo privado para venir así
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
Dado que muchas convenciones son para .Net y para mantener cierta uniformidad entre las convenciones de C # y VB.NET, están utilizando la misma.
Encontré la referencia de lo que estaba diciendo: http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices
Estuche Camel con guión bajo destacado. En VB.NET, siempre indique "Protegido" o "Privado", no use "Dim". Se desaconseja el uso de "m_", al igual que el uso de un nombre de variable que difiere de la propiedad por un solo caso, especialmente con variables protegidas, ya que viola el cumplimiento y hará que su vida sea difícil si programa en VB.NET, ya que tendría que nombrar a sus miembros como algo diferente de las propiedades de acceso / mutador. De todos los elementos aquí, el guión bajo principal es realmente el único controvertido. Personalmente, prefiero el caso de camello directo sin guión bajo para mis variables privadas, de modo que no tenga que calificar los nombres de variables con "esto". para distinguir de los parámetros en los constructores o en otros lugares donde probablemente tenga una colisión de nombres. Con la insensibilidad a mayúsculas y minúsculas de VB.NET, esto es aún más importante ya que sus propiedades de acceso generalmente tendrán el mismo nombre que sus variables de miembro privadas, excepto el guión bajo. En lo que respecta a m_, en realidad se trata solo de estética. Yo (y muchos otros) encuentro m_ feo, ya que parece que hay un agujero en el nombre de la variable. Es casi ofensivo. Solía usarlo en VB6 todo el tiempo, pero eso fue solo porque las variables no podían tener un guión bajo destacado. No podría estar más feliz de verlo desaparecer. Microsoft recomienda contra m_ (y la recta _) a pesar de que hicieron ambas cosas en su código. Además, el prefijo con una "m" recta es correcto. Por supuesto, dado que codifican principalmente en C #, pueden tener miembros privados que difieren solo en el caso de las propiedades. La gente de VB tiene que hacer otra cosa. En lugar de tratar de encontrar casos especiales de idioma por idioma, recomiendo el subrayado líder para todos los idiomas que lo admitirán. Si quiero que mi clase sea totalmente compatible con CLS, podría dejar el prefijo en cualquier variable miembro protegida de C #. En la práctica, sin embargo, nunca me preocupo por esto, ya que mantengo privadas todas las variables miembro potencialmente protegidas y en su lugar proporciono accesores y mutadores protegidos. Por qué: en pocas palabras, esta convención es simple (un carácter), fácil de leer (su ojo no se distrae con otros personajes principales) y evita con éxito nombrar colisiones con variables de nivel de procedimiento y propiedades de nivel de clase. . Recomiendo el guión bajo principal para todos los idiomas que lo admitirán. Si quiero que mi clase sea totalmente compatible con CLS, podría dejar el prefijo en cualquier variable miembro protegida de C #. En la práctica, sin embargo, nunca me preocupo por esto, ya que mantengo privadas todas las variables miembro potencialmente protegidas y en su lugar proporciono accesores y mutadores protegidos. Por qué: en pocas palabras, esta convención es simple (un carácter), fácil de leer (su ojo no se distrae con otros personajes principales) y evita con éxito nombrar colisiones con variables de nivel de procedimiento y propiedades de nivel de clase. . Recomiendo el guión bajo principal para todos los idiomas que lo admitirán. Si quiero que mi clase sea totalmente compatible con CLS, podría dejar el prefijo en cualquier variable miembro protegida de C #. En la práctica, sin embargo, nunca me preocupo por esto, ya que mantengo privadas todas las variables miembro potencialmente protegidas y en su lugar proporciono accesores y mutadores protegidos. Por qué: en pocas palabras, esta convención es simple (un carácter), fácil de leer (su ojo no se distrae con otros personajes principales) y evita con éxito nombrar colisiones con variables de nivel de procedimiento y propiedades de nivel de clase. . Nunca me preocupo por esto, ya que mantengo privadas todas las variables miembro potencialmente protegidas y, en su lugar, proporciono accesores y mutadores protegidos. Por qué: en pocas palabras, esta convención es simple (un carácter), fácil de leer (su ojo no se distrae con otros personajes principales) y evita con éxito nombrar colisiones con variables de nivel de procedimiento y propiedades de nivel de clase. . Nunca me preocupo por esto, ya que mantengo privadas todas las variables miembro potencialmente protegidas y, en su lugar, proporciono accesores y mutadores protegidos. Por qué: en pocas palabras, esta convención es simple (un carácter), fácil de leer (su ojo no se distrae con otros personajes principales) y evita con éxito nombrar colisiones con variables de nivel de procedimiento y propiedades de nivel de clase. .
El primer comentarista (R Samuel Klatchko) hizo referencia: ¿Cuáles son las reglas sobre el uso de un guión bajo en un identificador de C ++? que responde la pregunta sobre el guión bajo en C ++. En general, no debe utilizar un guión bajo, ya que está reservado para el implementador de su compilador. El código con el que está viendo _var
probablemente sea un código heredado o un código escrito por alguien que creció utilizando el antiguo sistema de nombres que no desaprobaba los guiones bajos.
Como dicen otras respuestas, solía usarse en C ++ para identificar variables de miembros de clase. Sin embargo, no tiene un significado especial en cuanto a decoradores o sintaxis. Entonces, si quieres usarlo, se compilará.
Dejaré la discusión de C # a otros.
_var no tiene significado y solo sirve para facilitar la distinción de que la variable es una variable miembro privada.
En C ++, usar la convención _var es una mala forma, porque hay reglas que rigen el uso del guión bajo delante de un identificador. _var está reservado como un identificador global, mientras que _Var (guión bajo + mayúscula) está reservado en cualquier momento. Esta es la razón por la cual en C ++, verá personas que usan la convención var_ en su lugar.
Puede crear sus propias pautas de codificación. Simplemente escriba una documentación clara para el resto del equipo.
Usar _field ayuda a Intelilsense a filtrar todas las variables de clase simplemente escribiendo _.
Por lo general, sigo las pautas de Brad Adams , pero recomienda no usar guiones bajos.
La denominación estándar de Microsoft para C # dice variables y parámetros deben utilizar el formulario caso de camellos menor IE: paramName
. La norma también exige a los campos siguen la misma forma, pero esto puede llevar a código claro tantos equipos requieren un prefijo de subrayado para mejorar la claridad IE: _fieldName
.
Con C #, las Directrices de diseño de Microsoft Framework sugieren no utilizar el carácter de subrayado para los miembros públicos . Para miembros privados , se pueden usar guiones bajos. De hecho, Jeffrey Richter (a menudo citado en las pautas) usa una m_ por ejemplo y una "s_" para miembros estáticos privados.
Personalmente, uso solo _ para marcar a mis miembros privados. "m_" y "s_" rayan en la notación húngara, que no solo está mal vista en .NET, sino que puede ser bastante detallada y encuentro que las clases con muchos miembros son difíciles de realizar un escaneo rápido alfabético (imagínese 10 variables, todas comenzando con m_) .
Uso el nombre _var para las variables miembro de mis clases. Hay 2 razones principales que hago:
1) Me ayuda a hacer un seguimiento de las variables de clase y las variables de función local cuando leo mi código más tarde.
2) Ayuda en Intellisense (u otro sistema de finalización de código) cuando busco una variable de clase. El simple hecho de conocer el primer carácter es útil para filtrar la lista de variables y métodos disponibles.
En lo que respecta a los lenguajes C y C ++, no hay un significado especial para un guión bajo en el nombre (principio, medio o final). Es solo un carácter de nombre de variable válido. Las "convenciones" provienen de las prácticas de codificación dentro de una comunidad de codificación.
Como ya se indicó en varios ejemplos anteriores, _ al principio puede significar miembros privados o protegidos de una clase en C ++.
Permítanme darles un poco de historia que puede ser una trivia divertida. En UNIX si tiene una función de biblioteca central C y un back-end del núcleo donde desea exponer la función del núcleo al espacio del usuario, también _ está atascado frente al código auxiliar de la función que llama a la función del núcleo directamente sin hacer nada más. El ejemplo más famoso y conocido de esto es exit () vs _exit () bajo los núcleos de tipo BSD y SysV: allí, exit () hace cosas de espacio de usuario antes de llamar al servicio de salida del kernel, mientras que _exit solo se asigna al servicio de salida del kernel.
Así que _ se usaba para cosas "locales" en este caso local como máquina local. Por lo general, _functions () no eran portátiles. En eso no debe esperar el mismo comportamiento en varias plataformas.
Ahora como para _ en nombres de variables, como
int _foo;
Bien psicológicamente, un _ es algo extraño tener que escribir al principio. Entonces, si desea crear un nombre de variable que tenga una menor probabilidad de un choque con otra cosa, ESPECIALMENTE cuando se trata de sustituciones preprocesador que desea, considere los usos de _.
Mi consejo básico sería seguir siempre la convención de su comunidad de codificación, para que pueda colaborar de manera más efectiva.
A muchas personas les gusta tener campos privados con el prefijo de subrayado. Es solo una convención de nombres.
Las convenciones de nomenclatura 'oficiales' de C # prescriben nombres simples en minúsculas (sin subrayado) para los campos privados.
No conozco las convenciones estándar para C ++, aunque los guiones bajos son muy utilizados.
Es solo una convención que algunos programadores usan para dejar en claro cuando se manipula un miembro de la clase o algún otro tipo de variable (parámetros, locales para la función, etc.). Otra convención que también se usa ampliamente para las variables miembro es prefijar el nombre con 'm_'.
De todos modos, estas son solo convenciones y no encontrará una sola fuente para todas ellas. Son una cuestión de estilo y cada equipo de programación, proyecto o empresa tiene el suyo (o incluso no tiene ninguno).
Hay una razón totalmente legítima para usarlo en C #: si el código también debe ser extensible desde VB.NET. (De lo contrario, no lo haría).
Dado que VB.NET no distingue entre mayúsculas y minúsculas, no hay una forma sencilla de acceder al field
miembro protegido en este código:
public class CSharpClass
{
protected int field;
public int Field { get { return field; } }
}
Por ejemplo, esto accederá al captador de propiedades, no al campo:
Public Class VBClass
Inherits CSharpClass
Function Test() As Integer
Return Field
End Function
End Class
Diablos, ni siquiera puedo escribir field
en minúsculas: VS 2010 sigue corrigiéndolo.
Para que sea fácilmente accesible a las clases derivadas en VB.NET, uno tiene que llegar a otra convención de nomenclatura. Prefijar un guión bajo es probablemente el menos intrusivo y el más "históricamente aceptado" de ellos.
Vieja pregunta, nueva respuesta (C #).
Otro uso de guiones bajos para C # es con la DI de ASP NET Core (inyección de dependencia). Las readonly
variables privadas de una clase que se asignó a la interfaz inyectada durante la construcción deberían comenzar con un guión bajo. Supongo que es un debate si usar subrayado para cada miembro privado de una clase (aunque Microsoft lo sigue), pero este es seguro.
private readonly ILogger<MyDependency> _logger;
public MyDependency(ILogger<MyDependency> logger)
{
_logger = logger;
}
Una convención de nomenclatura como esta es útil cuando está leyendo código, particularmente código que no es el suyo. Una convención de nomenclatura sólida ayuda a indicar dónde se define un miembro en particular, qué tipo de miembro es, etc. La mayoría de los equipos de desarrollo adoptan una convención de nomenclatura simple y simplemente prefijan los campos de miembros con un guión bajo ( _fieldName
). En el pasado, he usado la siguiente convención de nomenclatura para C # (que se basa en las convenciones de Microsofts para el código de marco .NET, que se puede ver con Reflector):
Campo de instancia: m_fieldName
Campo estático: s_fieldName Miembro
público / protegido / interno: PascalCasedName ()
Miembro privado: camelCasedName ()
Esto ayuda a las personas a comprender la estructura, el uso, la accesibilidad y la ubicación de los miembros cuando leen códigos desconocidos muy rápidamente.