14 maneras de simplificar su código C# - Ideas sobre las mejores prácticas de C# en el vídeo de Tim Corey
En su completo vídeo "14 maneras de simplificar su código C#", Tim Corey explora las mejores prácticas de C# que mejoran la legibilidad del código, reducen el desorden y mantienen su base de código mantenible. En lugar de obsesionarse con frases de una sola línea o trucos crípticos, Tim se centra en las buenas prácticas de codificación: cómo escribir código limpio y comprensible que otros desarrolladores puedan seguir.
Enmarca cada consejo en torno a ejemplos reales de Visual Studio, abordando convenciones de nomenclatura, gestión de errores e incluso cómo refactorizar código sin romper nada. No se trata sólo de teoría: la práctica mejora el código.
En este artículo, vamos a repasar cada una de las 14 formas que demostró.
1. Uso estático para un código más limpio
Tim comienza mostrando cómo el acceso estático puede simplificar las llamadas repetitivas. Al declarar:
using static System.Console;
using static System.Console;
ya no es necesario prefijar cada miembro estático con Console..
Se trata de algo más que de eliminar palabras: se trata de dejar claro el acceso estático. Tim señala que si se llama a un miembro estático definido en una clase de uso frecuente, como Console o Math, esta abreviatura mejora la legibilidad del código.
Sin embargo, como parte de las buenas prácticas de codificación, advierte que los desarrolladores deben evitar conflictos: dos clases diferentes pueden tener el mismo nombre para un miembro estático. El conocimiento de posibles comportamientos inesperados es clave.
2. Inicialización de listas con
C# permite ahora inicializar listas de forma más directa:
List<string> names = ["Tim", "Sue", "Bilbo"];
List<string> names = ["Tim", "Sue", "Bilbo"];
Tim explica que no se trata de exprimirlo todo en un solo enunciado, sino de escribir código que sea más fácil de leer y optimizar el rendimiento reduciendo la ceremonia.
En lugar de analizar el texto repetitivo "nueva lista de cadenas", el lector ve exactamente lo que importa: los nombres descriptivos de la colección. Tim también señala que esto funciona para matrices e incluso diccionarios, alineándose con las convenciones de codificación que priorizan la claridad.
3. Destinatarios nuevos
Otro ahorro de tiempo: nuevo tipo de destino. En lugar de:
List<int> numbers = new List<int>();
List<int> numbers = new List<int>();
puedes escribir:
List<int> numbers = new();
List<int> numbers = new();
Tim subraya que repetir el nombre de la clase es innecesario, ya está en el lado izquierdo. Esto sigue las buenas prácticas de codificación, ya que elimina la redundancia y facilita el análisis de la base de código.
4. Tipos var y anónimos
Tim aborda el tema de var, una característica que suscita debate en los círculos de prácticas de codificación. A algunos no les gusta por ocultar nombres y tipos de variables, pero Tim aclara que su verdadero poder reside en los tipos anónimos.
Al trabajar con fuentes de datos (como SQL a través de Dapper), Tim muestra cómo var permite crear objetos sobre la marcha:
var parameters = new { FirstName = "Tim", LastName = "Corey" };
var parameters = new { FirstName = "Tim", LastName = "Corey" };
Esto es perfecto para escribir consultas u objetos puntuales: no es necesario crear una clase base sólo para los parámetros. Como dice Tim, así se evita contaminar la base de código con tipos innecesarios, al tiempo que se proporcionan mensajes de error significativos si algo va mal.
5. Espacios de nombres en archivos
Tim pasa a los espacios de nombres de archivos, mostrando cómo esto:
namespace ProjectName
{
// indented code
}
namespace ProjectName
{
// indented code
}
se convierte en esto:
namespace ProjectName;
namespace ProjectName;
Este pequeño cambio elimina el desperdicio de sangría y se adhiere a las convenciones de nomenclatura de C#, como el uso de Pascal para los miembros públicos. Tim explica que, dado que la mayoría de los archivos contienen un solo espacio de nombres, esto mejora la legibilidad del código y mantiene alineadas las secciones lógicas.
6. Registros para estructuras de datos de una línea
El uso de registros permite definir objetos de datos en una sola sentencia:
public record EmployeeRecord(int Id, string Name);
public record EmployeeRecord(int Id, string Name);
Tim señala que esto genera un tipo completo -propiedades, inmutabilidad y ToString()- con un esfuerzo mínimo. Deja claro que los escenarios de clases derivadas siguen requiriendo clases, pero cuando tu objeto es de sólo lectura, los registros siguen el principio de responsabilidad única haciendo bien un solo trabajo.
7. Concordancia de patrones
Tim demuestra cómo la concordancia de patrones ayuda a manejar excepciones y a realizar comparaciones de forma segura. En lugar de escribir verbosas comprobaciones de tipo, puedes combinarlas:
if (emp is EmployeeRecord e)
{
e.Id = 1;
}
if (emp is EmployeeRecord e)
{
e.Id = 1;
}
Esta línea única comprueba y calca. Tim dice que esto está en consonancia con las buenas prácticas de codificación: hay que evitar los nombres de variables de una sola letra, como x o y, y en su lugar dar nombres descriptivos como e. Los nombres claros de métodos y variables facilitan el mantenimiento del código por parte de otros desarrolladores.
8. Interpolación de cadenas
Para construir cadenas legibles, Tim demuestra la interpolación de cadenas:
$"The employee with ID {e.Id} is {e.Name}"
$"The employee with ID {e.Id} is {e.Name}"
Señala que así resulta más fácil dar sentido a los mensajes de error y escribir comentarios. En lugar de una concatenación enmarañada, puede escribir literalmente código que se lea como en inglés, mejorando la calidad del código y simplificando las futuras pruebas unitarias que comprueben la salida.
9. nameof() para una refactorización segura
Tim muestra cómo nameof() te protege cuando refactorizas código. Los nombres de variables codificados en cadenas pueden provocar comportamientos inesperados si se les cambia el nombre. Pero escribiendo:
nameof(emp)
nameof(emp)
el compilador actualiza automáticamente cada uso. Esta es una de esas buenas prácticas que mantienen sana tu base de código cuando escribes limpio y reorganizas el código.
10. Tuplas para múltiples valores de retorno
En lugar de crear una clase base sólo para devolver dos valores, Tim utiliza tuplas:
(string FirstName, string LastName) SplitName(string fullName)
(string FirstName, string LastName) SplitName(string fullName)
Esto evita dependencias externas innecesarias y se adhiere al principio de responsabilidad única: el método solo divide un nombre, nada más. Como dice Tim, la práctica mejora el código cuando se evita el exceso de ingeniería.
11. Deconstrucción
Basándose en tuplas, Tim muestra cómo deconstruir resultados en variables locales:
var (firstName, lastName) = SplitName("Tim Corey");
var (firstName, lastName) = SplitName("Tim Corey");
De este modo, los nombres de las variables serán descriptivos y se evitará una sintaxis críptica de las tuplas. Tim incluso aborda el tema de descartar valores no utilizados (mediante _), lo que indica la intención: nada de dejar nombres de variables de una sola letra sin explicar.
12. Descartes de valores innecesarios
Si no necesitas todas las partes de la tupla, Tim recomienda descartarlas:
var (firstName, _) = SplitName("Tim Corey");
var (firstName, _) = SplitName("Tim Corey");
Esto muestra a otros desarrolladores que se está ignorando intencionadamente un valor, lo que es bueno para probar marcos de trabajo o pruebas unitarias en las que no todos los resultados importan.
13. Uso de sentencias sin bloques
Tim se adentra en la gestión de recursos y la gestión de errores. Anteriormente, escribirías:
using (var connection = new SqlConnection(connString))
{
// work
}
using (var connection = new SqlConnection(connString))
{
// work
}
Ahora, puede utilizar:
using var connection = new SqlConnection(connString);
using var connection = new SqlConnection(connString);
Esto se ajusta a los principios SOLID, en concreto al principio de responsabilidad única y al principio de inversión de dependencias. Tim señala que esta sintaxis funciona bien para dependencias externas como las bases de datos, asegurando que la mayoría del manejo de excepciones sea más limpio y que las conexiones siempre se cierren, evitando problemas de rendimiento o incluso escenarios de inyección SQL cuando las conexiones no se eliminan.
14. Declaraciones de variables inline out
Por último, Tim cubre las declaraciones de variables inline out para cosas como el análisis sintáctico:
if (int.TryParse(numberText, out int numberValue))
if (int.TryParse(numberText, out int numberValue))
Aquí se crea la variable local en la misma línea. Esto mantiene las convenciones de codificación estrictas y los nombres de los métodos descriptivos. Al mantener el código correctamente agrupado, se reduce el comportamiento inesperado y se hacen más seguros los futuros esfuerzos de refactorización del código.
Resumen
Tim concluye su vídeo recordando a los espectadores que estas simplificaciones no consisten en escribir frases crípticas de una sola línea, sino en aplicar buenas prácticas de codificación. Características como el uso de estática, registros, concordancia de patrones, tuplas y descartes le permiten escribir C# limpio y moderno.
Anima a los desarrolladores a pensar en las convenciones de nomenclatura, la gestión de errores y los nombres significativos a medida que adoptan estas funciones. "El código está pensado para ser leído por humanos", dice Tim, y cuando escribes código que es fácil de entender, mejoras tu vida y la de otros desarrolladores.
En resumen: adopte estas prácticas recomendadas de C#, siga los principios SOLID, como el principio de responsabilidad única, el principio de segregación de interfaces y el principio de inversión de dependencias, y su código no solo compilará, sino que mejorará el rendimiento, reducirá los comportamientos inesperados y mantendrá a su equipo feliz codificando.
