Estándares de Codificación y Convenciones de Nombres en C#
Hablaremos sobre convenciones de código y buenas prácticas.
| Nombre del Objeto | Notación | Longitud | Plural | Prefijo | Sufijo | Abreviación | Máscara de Caracteres | Guiones Bajos |
|---|---|---|---|---|---|---|---|---|
| Nombre de namespace | PascalCase | 128 | Sí | Sí | No | No | [A-z][0-9] | No |
| Nombre de clase | PascalCase | 128 | No | No | Sí | No | [A-z][0-9] | No |
| Nombre de constructor | PascalCase | 128 | No | No | Sí | No | [A-z][0-9] | No |
| Nombre de método | PascalCase | 128 | Sí | No | No | No | [A-z][0-9] | No |
| Argumentos de método | camelCase | 128 | Sí | No | No | Sí | [A-z][0-9] | No |
| Variables locales | camelCase | 50 | Sí | No | No | Sí | [A-z][0-9] | No |
| Nombre de constantes | PascalCase | 50 | No | No | No | No | [A-z][0-9] | No |
| Campo público | PascalCase | 50 | Sí | No | No | Sí | [A-z][0-9] | No |
| Campo privado | _camelCase | 50 | Sí | No | No | Sí | _[A-z][0-9] | Sí |
| Nombre de propiedades | PascalCase | 50 | Sí | No | No | Sí | [A-z][0-9] | No |
| Nombre de delegado | PascalCase | 128 | No | No | Sí | Sí | [A-z] | No |
| Nombre de tipo enum | PascalCase | 128 | Sí | No | No | No | [A-z] | No |
1. Utiliza PascalCase para nombres de clases y métodos:
public class ClientActivity
{
public void ClearStatistics()
{
//...
}
public void CalculateStatistics()
{
//...
}
}
Por qué: es consistente con el Framework .NET de Microsoft y facilita la lectura.
2. Utiliza camelCase para argumentos de métodos y variables locales:
public class UserLog
{
public void Add(LogEvent logEvent)
{
int itemCount = logEvent.Items.Count;
// ...
}
}
Por qué: es consistente con el Framework .NET de Microsoft y facilita la lectura.
3. No utilices notación húngara ni identificadores que indiquen el tipo
// Correcto
int counter;
string name;
// Evitar
int iCounter;
string strName;
Por qué: Visual Studio permite identificar fácilmente los tipos mediante tooltips. En general, evita incluir información de tipo en los identificadores.
4. No utilices MAYÚSCULAS COMPLETAS para constantes o variables readonly:
// Correcto
public const string ShippingType = "DropShip";
// Evitar
public const string SHIPPINGTYPE = "DropShip";
Por qué: es consistente con el Framework .NET de Microsoft. Las mayúsculas completas llaman demasiado la atención visualmente.
5. Utiliza nombres significativos para las variables
El siguiente ejemplo utiliza seattleCustomers para representar clientes ubicados en Seattle:
var seattleCustomers = from customer in customers
where customer.City == "Seattle"
select customer.Name;
Por qué: es consistente con el Framework .NET de Microsoft y facilita la lectura.
6. Evita abreviaciones
Excepciones: abreviaciones ampliamente utilizadas como Id, Xml, Ftp, Uri.
// Correcto
UserGroup userGroup;
Assignment employeeAssignment;
// Evitar
UserGroup usrGrp;
Assignment empAssignment;
// Excepciones
CustomerId customerId;
XmlDocument xmlDocument;
FtpHelper ftpHelper;
UriPart uriPart;
Por qué: evita abreviaciones inconsistentes y mejora la legibilidad.
7. Utiliza PascalCase o camelCase para abreviaciones de 3 caracteres o más
(Las abreviaciones de 2 caracteres se escriben completamente en mayúsculas cuando corresponde).
HtmlHelper htmlHelper;
FtpTransfer ftpTransfer, fastFtpTransfer;
UIControl uiControl, nextUIControl;
Por qué: es consistente con el Framework .NET de Microsoft. Las mayúsculas excesivas generan ruido visual.
8. No utilices guiones bajos en identificadores
Excepción: los campos privados pueden comenzar con _.
// Correcto
public DateTime clientAppointment;
public TimeSpan timeLeft;
// Evitar
public DateTime client_Appointment;
public TimeSpan time_Left;
// Excepción (campo de clase)
private DateTime _registrationDate;
Por qué: hace el código más natural de leer y evita problemas visuales con los subrayados.
9. Utiliza los alias de tipos de C# (int, float, string, etc.) para declaraciones locales, parámetros y miembros
Utiliza los nombres del Framework (Int32, String, etc.) cuando accedas a miembros estáticos del tipo.
// Correcto
string firstName;
int lastIndex;
bool isSaved;
string commaSeparatedNames = String.Join(", ", names);
int index = Int32.Parse(input);
// Evitar
String firstName;
Int32 lastIndex;
Boolean isSaved;
string commaSeparatedNames = string.Join(", ", names);
int index = int.Parse(input);
Por qué: hace el código más natural de leer y mantiene consistencia con .NET.
10. Utiliza var para declaraciones de variables locales
Excepción: tipos primitivos (int, string, double, etc.).
var stream = File.Create(path);
var customers = new Dictionary();
// Excepciones
int index = 100;
string timeSheet;
bool isCompleted;
Por qué: reduce ruido visual, especialmente con tipos genéricos complejos.
11. Utiliza sustantivos o frases nominales para nombrar clases
public class Employee
{
}
public class BusinessLocation
{
}
public class DocumentCollection
{
}
Por qué: son más fáciles de recordar y siguen las convenciones de .NET.
12. Prefija las interfaces con la letra I
Los nombres deben ser sustantivos o adjetivos.
public interface IShape
{
}
public interface IShapeCollection
{
}
public interface IGroupable
{
}
Por qué: es consistente con el Framework .NET de Microsoft.
13. Nombra los archivos fuente según su clase principal
Excepción: clases parciales (partial) que reflejan su propósito.
// Ubicado en Task.cs
public partial class Task
{
}
// Ubicado en Task.generated.cs
public partial class Task
{
}
Por qué: facilita la organización y mantiene juntas las clases parciales.
14. Organiza los namespaces con una estructura clara
namespace Company.Technology.Feature.Subnamespace
{
}
namespace Company.Product.Module.SubModule
{
}
namespace Product.Module.Component
{
}
namespace Product.Layer.Module.Group
{
}
Por qué: mantiene una buena organización de la base de código.
15. Alinea verticalmente las llaves
// Correcto
class Program
{
static void Main(string[] args)
{
//...
}
}
Por qué: aunque Microsoft utiliza otro estándar, muchos desarrolladores prefieren esta alineación por legibilidad.
16. Declara todas las variables miembro al inicio de la clase
Las variables estáticas deben ir primero.
public class Account
{
public static string BankName;
public static decimal Reserves;
public string Number { get; set; }
public DateTime DateOpened { get; set; }
public DateTime DateClosed { get; set; }
public decimal Balance { get; set; }
// Constructor
public Account()
{
// ...
}
}
Por qué: evita tener que buscar declaraciones distribuidas por toda la clase.
17. Utiliza nombres singulares para enums
Excepción: enums de banderas (Flags).
// Correcto
public enum Color
{
Red,
Green,
Blue,
Yellow,
Magenta,
Cyan
}
// Excepción
[Flags]
public enum Dockings
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}
Por qué: un enum representa un único valor. Los enums con Flags pueden contener varios valores simultáneamente.
18. No especifiques explícitamente el tipo subyacente ni los valores de un enum
Excepto para enums con Flags.
// No recomendado
public enum Direction : long
{
North = 1,
East = 2,
South = 3,
West = 4
}
// Correcto
public enum Direction
{
North,
East,
South,
West
}
Por qué: evita dependencias innecesarias en valores o tipos concretos.
19. No utilices el sufijo Enum en nombres de enums
// No recomendado
public enum CoinEnum
{
Penny,
Nickel,
Dime,
Quarter,
Dollar
}
// Correcto
public enum Coin
{
Penny,
Nickel,
Dime,
Quarter,
Dollar
}
Por qué: evita indicadores de tipo redundantes.
20. No utilices los sufijos Flag o Flags en nombres de enums
// No recomendado
[Flags]
public enum DockingsFlags
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}
// Correcto
[Flags]
public enum Dockings
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}
Por qué: evita indicadores de tipo redundantes.
21. Utiliza el sufijo EventArgs al crear clases que contienen información de eventos
public class BarcodeReadEventArgs : System.EventArgs
{
}
Por qué: es consistente con el Framework .NET de Microsoft y fácil de identificar.
22. Utiliza el sufijo EventHandler para los delegados de eventos
public delegate void ReadBarcodeEventHandler(
object sender,
ReadBarcodeEventArgs e);
Por qué: es consistente con el Framework .NET de Microsoft y fácil de identificar.
23. No crees parámetros que solo se diferencien por mayúsculas y minúsculas
// Evitar
private void MyFunction(string name, string Name)
{
//...
}
Por qué: dificulta la lectura y puede generar errores o confusión.
24. Utiliza los parámetros sender y e en los manejadores de eventos
public void ReadBarcodeEventHandler(
object sender,
ReadBarcodeEventArgs e)
{
//...
}
Por qué: es consistente con las convenciones estándar de .NET.
25. Utiliza el sufijo Exception al crear clases de excepción
public class BarcodeReadException : System.Exception
{
}
Por qué: facilita identificar excepciones personalizadas.
26. Utiliza prefijos como Is, Has, Can, Any para identificadores booleanos
public static bool IsNullOrEmpty(string value)
{
return value == null || value.Length == 0;
}
Por qué: mejora la legibilidad y expresa claramente una condición booleana.
27. Utiliza argumentos nombrados en las llamadas a métodos
Al llamar a un método, pasa el nombre del parámetro seguido de : y su valor.
// Método
public void DoSomething(string foo, int bar)
{
...
}
// Evitar
DoSomething("someString", 1);
// Correcto
DoSomething(foo: "someString", bar: 1);
Por qué: mejora la legibilidad y evita depender del orden de los parámetros.
#Referencias Oficiales
- MSDN - General Naming Conventions
- DoFactory - C# Coding Standards and Naming Conventions
- MSDN - Naming Guidelines
- MSDN - Framework Design Guidelines
- Microsoft Learn - Common C# Coding Conventions
- GitHub - C# Coding Style