C# para Expertos y Arquitectos
Este es el nivel más alto. Aquí no solo importa el qué, sino el porqué. Evaluamos tu capacidad para tomar decisiones de arquitectura, optimizar el rendimiento y utilizar las características más avanzadas del runtime de .NET.
¿Qué evaluaremos?
1. Rendimiento y Gestión de Memoria
- Stack vs. Heap a Fondo:
stackallocpermite reservar memoria directamente en el stack, evitando por completo al Garbage Collector. Esto es una técnica de micro-optimización para rutas de código críticas (hot paths). - Referencias Débiles: Una
WeakReferencepermite mantener una referencia a un objeto sin impedir que el GC lo elimine si no hay otras referencias fuertes. Es la base para construir cachés que no provoquen fugas de memoria. - Optimización de Inicialización: El atributo
[SkipLocalsInit]es una instrucción al compilador para que no emita la banderalocalsinit, evitando la inicialización a cero de las variables locales en el stack. De nuevo, una micro-optimización para código de ultra-alto rendimiento.
2. Concurrencia y Paralelismo
- Primitivas de Sincronización: Más allá del
lock, un experto debe saber cuándo usarSemaphoreSlim(para limitar el acceso a un pool de recursos) oMutex(para sincronización entre procesos). - Contexto de Sincronización: Usar
ConfigureAwait(false)en el código de una biblioteca es crucial para prevenir deadlocks en aplicaciones con un contexto de sincronización (como UI o ASP.NET clásico), ya que le indica alawaitque no necesita volver al hilo original.
3. Arquitectura y Metaprogramación
- Inyección de Dependencias (DI): El problema de la “dependencia cautiva” (
Captive Dependency) ocurre cuando un servicio de ciclo de vida largo (ej.Singleton) depende de uno de ciclo de vida corto (ej.Scoped). El servicio Scoped queda “atrapado” y se convierte efectivamente en un Singleton, lo cual puede causar bugs y fugas de memoria. - Expression Trees: EF Core los usa para convertir tus consultas LINQ de C# en árboles de expresión que pueden ser traducidos a SQL. Esto es metaprogramación: tratar el código como datos.
- Source Generators: A diferencia de la reflexión (que ocurre en tiempo de ejecución), los Source Generators se ejecutan en tiempo de compilación para analizar el código del usuario y generar archivos de código adicionales que se compilan junto con el resto del proyecto. Es una forma de metaprogramación mucho más performante.
- Inmutabilidad: Las propiedades
init-onlyde C# 9+ permiten crear objetos inmutables de una forma mucho más limpia que antes, asegurando que su estado no pueda cambiar después de la inicialización.
Si dominas estos temas, estás operando al más alto nivel de ingeniería de software con .NET.