
Como sabéis, hasta ahora, los componentes Blazor podían ejecutarse en dos tipos de hosting distintos, Blazor Server y Blazor WebAssembly. Aunque cada uno tiene sus escenarios ideales de uso, ambos enfoques conseguían lo mismo, implementar Single Page Applications en C#, sin necesidad de utilizar JavaScript (bueno, o al menos, minimizando radicalmente su uso):
- Con Blazor Server, se mantiene en el servidor una copia del DOM de cada usuario conectado, de forma que C# puede manipularlo directamente. Luego, mediante una conexión websockets, se sincronizan los cambios con el cliente.
- Blazor WebAssembly lleva al navegador el runtime de .NET, las bibliotecas base y los ensamblados de la aplicación, por lo que todo se ejecuta directamente en el lado cliente gracias a WebAssembly.
Estas dos formas de ejecutar componentes son muy apropiadas cuando se trata de elementos interactivos, capaces de responder a eventos de usuarios y con capacidad de actualizar el contenido de la página. Sin embargo, son muy poco eficientes cuando se trata de páginas estáticas que no requieren interacción con el usuario:
-
Para poder mostrar en el navegador un contenido, en Blazor Server hay que esperar a que el lado cliente descargue la página contenedora, un archivo JavaScript y se establezca la conexión websockets con el servidor, tras lo cual se enviará el contenido de la página.
-
En Blazor WebAssembly, el cliente debe descargar la página contenedora, los ensamblados y todo el entorno de ejecución de .NET y lanzarlo todo sobre WebAssembly. En este momento se puede mostrar el contenido de la página.

Sabemos que está feo y no sea especialmente recomendable en muchos casos, pero hay veces en las que es totalmente necesario acceder a miembros privados de una clase. Por ejemplo, sería un requisito imprescindible si fuéramos a implementar un serializador o deserializador personalizado, o necesitásemos clonar objetos, o simplemente realizar pruebas unitarias a una clase que no ha sido diseñada para ello.
Para conseguirlo, siempre hemos utilizado los mecanismos de introspección de .NET, conocidos por todos como reflexión o por su término en inglés reflection. Por ejemplo, imaginemos una clase como la siguiente, virtualmente inexpugnable:
public class BlackBox
{
private string _message = "This is a private message";
private void ShowMessage(string msg) => Console.WriteLine(msg);
public override string ToString() => _message;
}
Aunque a priori no podemos hacer nada con ella desde fuera, usando reflexión podríamos acceder sin problema a sus miembros privados, ya sean propiedades, campos, métodos o cualquier tipo de elemento, como podemos ver en el siguiente ejemplo:
var instance = new BlackBox();
// Obtenemos el valor del campo privado _message:
var field = typeof(BlackBox)
.GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance);
var value = field!.GetValue(instance);
// Ahora llamamos al método privado ShowMessage():
var method = typeof(BlackBox)
.GetMethod("ShowMessage", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(instance, [value]);
// Al ejecutar, se nuestra en consola: "This is a private message"
Sin embargo, de todos es sabido que la reflexión es un mecanismo muy lento, a veces farragoso en su implementación y, sobre todo, incompatible con tree-shaking, que es como se suele llamar la técnica que usan los compiladores de eliminar del código final todas las clases, métodos y propiedades que no se utilizan en el código final. Esta técnica va tomando cada vez más relevancia conforme los compiladores son capaces de crear directamente ejecutables nativos puros, porque permiten reducir de forma considerable el peso de los artefactos creados.
Por esta razón, en .NET 8 se ha incluido una nueva fórmula para acceder a miembros privados, mucho más eficiente y amistosa con AOT, porque se lleva a tiempo de compilación algo que antes obligatoriamente se resolvía en tiempo de ejecución.

Seguro que más de una vez habéis tenido que construir una abstracción sobre DateTime
para poder controlar apropiadamente la obtención de la fecha/hora actual y otras operaciones relacionadas con el tiempo.
Suelen ser bastante útiles cuando creamos pruebas unitarias de métodos que dependan del momento actual. Por ejemplo, ¿cómo testearíamos de forma automática que las dos líneas de ejecución del siguiente método DoSomething()
funcionan correctamente? Sería imposible salvo que ejecutásemos las pruebas a una hora determinada, algo que se antoja complicado 😉
public class MyClass
{
public string DoSomething()
{
var now = DateTime.Now;
return now.Second == 0
? "A new minute is starting"
: "Current second " + now.Second;
}
}
Sin duda, una forma mejor y más test friendly sería contar con una abstracción sobre el proveedor de tiempos capaz de retornar la fecha y hora actual, por ejemplo:
public interface IDateTimeProvider
{
DateTime GetCurrentDateTime();
}
De esta forma, podríamos reescribir la clase MyClass
de forma que recibiera por inyección de dependencias nuestro proveedor IDateTimeProvider
. Así sería realmente sencillo crear un par de pruebas unitarias que, suministrando los valores correctos a través de esta dependencia, podrían recrear los escenarios a cubrir:
public class MyClass
{
private readonly IDateTimeServices _dateTimeServices;
public TimeHelpers(IDateTimeServices dateTimeServices)
{
_dateTimeServices = dateTimeServices;
}
public string DoSomething()
{
var now = _dateTimeServices.GetCurrentDateTime();
return now.Second == 0
? "A new minute is starting"
: "Current second " + now.Second;
}
}
Aunque hacerlo de esta manera en nuestras aplicaciones es lo ideal, hay partes que se quedarían fuera de esta posibilidad, como las bibliotecas de terceros que de alguna forma dependan de las funcionalidades proporcionadas por DateTime
.
Por esta razón, .NET 8 va a introducir una abstracción que nos permitirá gestionar estos escenarios de forma más homogénea y generalizada en aplicaciones y componentes .NET.
Os presento la clase abstracta TimeProvider
😁

Versión tras versión, Entity Framework Core sigue introduciendo novedades que lo hacen cada vez más potente y atractivo para los desarrolladores. Sin ir más lejos, EF7, la última entrega disponible, incorporó bastantes mejoras en términos de rendimiento, soporte para columnas JSON, mapeo TPC, mapeo a procedimientos almacenados y muchas otras.
Pero una de las novedades que me resultó más interesante, quizás por ser muy esperada, fue la posibilidad de realizar borrados y actualizaciones de forma masiva sin tener que recurrir a lanzar directamente comandos SQL. O dicho de otra forma, con EF7 podremos ejecutar sentencias DELETE
y UPDATE
sobre la base de datos sin abandonar LINQ :)

El pattern matching de C# proporciona la capacidad de analizar expresiones para ver si cumplen determinados "patrones" o presentan características determinadas. Podéis ver algunos ejemplos interesantes en el post Un vistazo a los patrones relacionales y combinadores.
Aunque ya los tengo bastante interiorizados y hago uso de ellos cuando toca, todavía no se me ha dado el caso de necesitar los patrones de listas, introducidos hace unos meses en C# 11. Así que no está de más echarles un vistazo para cuando se dé la ocasión 😉

Desde la llegada de ASP.NET Core, hace ya algunos años, muchos hemos echado de menos el filtro [OutputCache]
de ASP.NET MVC "clásico". Aunque el nuevo framework ofrece alternativas interesantes para gestionar la caché tanto en el lado cliente como en el servidor, ninguna aportaba las funcionalidades que este filtro nos ofrecía.
Como recordaréis, a diferencia de las opciones ofrecidas actualmente por ASP.NET Core, como el filtro [ResponseCache]
o el middleware ResponseCaching
, que básicamente se regían por los encabezados presentes en peticiones y respuestas HTTP, el filtro [OutputCache]
es una solución de caché residente exclusivamente en el servidor. En este caso, la decisión de si el resultado a una petición se almacena o no se realiza completamente desde la aplicación, de forma totalmente independiente a encabezados o requisitos procedentes del lado cliente.
En ASP.NET Core 7 este filtro ha vuelto a la vida en forma de middleware, que ofrece sus funcionalidades con dos sabores distintos:
- Con anotaciones aplicables a endpoints implementados con Minimal API.
- Como filtro, aplicable a controladores y acciones MVC.
Echémosles un vistazo.

Otra de las novedades del flamante C# 11 viene a romper una limitación histórica: la ausencia de tipos genéricos en la definición de atributos.
Hasta esta versión del lenguaje, cuando necesitábamos introducir referencias a tipos de datos en un atributo, debíamos pasar obligatoriamente por el uso de un System.Type
y el verboso operador typeof()
. Además de incómodo, no había forma de limitar los tipos suministrados, dando lugar a errores en tiempo de ejecución que bien podrían haber sido resueltos el compilación con las herramientas apropiadas.
Dicho así quizás sea difícil de entender, pero veámoslo con un ejemplo.

La llegada de C#11 viene acompañada de un buen número de novedades, algunas de ellas bastante jugosas, como los raw string literals o el nuevo modificador "file" que ya hemos ido viendo por aquí.
En esta ocasión, vamos a echar el vistazo a otra de las novedades que pueden resultar de bastante utilidad en nuestro día a día: los miembros requeridos.

Modificadores de visibilidad habituales como internal
, public
o private
nos acompañan desde los inicios de C#, permitiéndonos definir desde dónde queremos permitir el acceso a los tipos que definimos en nuestras aplicaciones. Así podemos indicar, por ejemplo, que una clase pueda ser visible sólo a miembros definidos en su mismo ensamblado, que pueda ser utilizada desde cualquier punto, o que un tipo anidado sólo pueda verse desde el interior de su clase contenedora.
Pues bien, C# 11 traerá novedades al respecto ;)
Disclaimer: lo que vamos a ver aquí es válido en la RC2 de .NET 7, pero aún podría sufrir algún cambio para la versión final, prevista para noviembre de 2022.

De casualidad me he topado con un interesante cambio que .NET 5 introdujo en los componentes de serialización y deserialización System.Text.Json
y que, al menos para mí, pasó totalmente desapercibido en su momento. Por eso, he pensado que quizás sea buena idea dejarlo por aquí, por si hay algún despistado más al que pueda resultar útil.
Como seguro sabéis, al usar los componentes de System.Text.Json
para serializar o deserializar una clase, utilizamos el atributo [JsonIgnore]
para marcar las propiedades que queremos que sean ignoradas al convertir desde y hacia JSON.
Por ejemplo, dada la siguiente clase:
class User
{
public int Id { get; set; }
public string Email { get; set; }
[JsonIgnore]
public string Token { get; set; }
}
En ella estamos indicando expresamente que la propiedad Token
debe ser ignorada, por lo que ésta no aparecerá si serializamos un objeto a JSON:
var user = new User { Id = 42, Email = "john@server.com", Token = "ABCDEF"};
Console.WriteLine(JsonSerializer.Serialize(user));
// Result:
{"Id":42,"Email":"john@server.com"}
Y lo mismo ocurre en sentido contrario:
var jsonStr = "{ \"Id\": 42, \"Email\": \"john@server.com\", \"Token\": \"ABCDEF\"}";
var user = JsonSerializer.Deserialize<User>(jsonStr);
// ¡user.Token es nulo aquí!

Visual Studio sigue introduciendo novedades versión tras versión, y es fácil que algunas de ellas nos pasen desapercibidas y tardemos algún tiempo en conocerlas, o incluso en verles la utilidad. Un ejemplo lo tenemos en los breakpoints temporales y dependientes, dos nuevos tipos de puntos de interrupción añadidos en la versión 2022 que pueden venirnos bien a la hora de depurar aplicaciones.
En este post vamos a echarles un vistazo, por si hay algún despistado más que no se haya dado cuenta de estas novedades.

Aún no hemos terminado de asimilar las novedades de C# 10, cuando ya empiezan a llegar noticias de lo que encontraremos en la próxima versión, C# 11, que si todo va bien se lanzará en noviembre de este año.
Una de las que más me ha llamado la atención de momento es la llegada de raw string literals, una característica que mejorará bastante la posibilidad de escribir constantes de cadena multilínea en nuestro código.
Veamos en qué consiste.
Disclaimer: la nueva versión de C# está aún en desarrollo, y detalles de los que veamos aquí podrían cambiar antes de lanzarse definitivamente.

Seguimos descubriendo novedades aparecidas con .NET 6, y ahora le toca el turno a la nueva clase PeriodicTimer
, una fórmula para la ejecución de tareas periódicas en contextos asíncronos que evita el uso de los clásicos callbacks a los que nos tenía acostumbrados el framework.
Como recordaréis, .NET dispone de un buen número de formas de implementar temporizadores, o timers, para ejecutar tareas en intervalos periódicos. El más conocido probablemente sea el clásico System.Threading.Timer
, en el que especificábamos el callback o método que debía ejecutarse en cada intervalo de tiempo mediante un delegado (en el siguiente ejemplo, mediante una lambda):
var timer = new System.Threading.Timer(o =>
{
Console.WriteLine("Hey! " + DateTime.Now.ToLongTimeString());
}, null, 0, 1000);
Console.ReadKey();
Hey! 12:25:51
Hey! 12:25:52
Hey! 12:25:53
Hey! 12:25:54
Hey! 12:25:55
_
Pero también existía System.Timers.Timer
, que nos permitía lograr algo parecido, aunque esta el callback lo implementábamos mediante una suscripción al evento Elapsed
del objeto:
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (sender, eventArgs) =>
{
Console.WriteLine("Hey! " + DateTime.Now.ToLongTimeString());
};
timer.Start();
Console.ReadKey();
Existían algunas fórmulas más específicas para plataformas concretas, como las clases System.Windows.Forms.Timer
, System.Web.UI.Timer
u otras. Sin embargo, todas coincidían en varias cosas:
- Utilizaban callbacks de alguna u otra forma, lo que implica un cierto riesgo de leaks de memoria y problemas con los tiempos de vida de objetos cuando la cosa se complica.
- Los callbacks no permitían código asíncrono, lo que podía llevarnos a luchar contra los engorrosos escenarios de ejecución de código asíncrono en entornos síncronos (async-over-sync).
- Podían darse casos de superposición u overlapping entre las distintas ejecuciones, cuando éstas tardaban en completarse más que el intervalo de definido en el timer.

Hace ya mucho tiempo que C# inició un interesante camino para conseguir reducir la cantidad de código necesario para hacer cosas frecuentes, introduciendo la capacidad de hacer implícitas determinadas construcciones y, por tanto, ahorrándonos tiempo y pulsaciones de teclas innecesarias.
En esta línea, todos recordaréis el tipado implícito, que tanto debate abrió en el lanzamiento de C# 3, hace ya casi quince años:
// Antes de C# 3
List<string> strings = new List<string>();
// Usando tipado implícito
var strings = new List<string>();
Bastante tiempo después, ya con C# 10, el lenguaje nos regaló una nueva característica que iba en la misma dirección, las expresiones new
con el tipo destino. Éstas permitían construir objetos usando tipado implícito, aunque esta vez en el lado derecho de las expresiones:
// Antes de C# 10
public class MyClass
{
private Invoice invoice = new Invoice(123);
private Dictionary<string, Person> people = new Dictionary<string, Person>();
...
}
// Ahora
public class MyClass
{
private Invoice invoice = new (123);
private Dictionary<string, Person> people = new ();
...
}
También en C# 10 nos hemos encontrado con los using
globales y using
implícitos, características ambas que nos permiten economizar esfuerzos evitando la introducción repetitiva de directivas para la importación de namespaces en el código.
Pues bien, aquí viene la siguiente vuelta de tuerca :) Unas semanas atrás, Immo Landwerth (Program manager de .NET en Microsoft) sorprendía a todos con esta afirmación sobre una de las características principales del próximo C# 11:


Parece que uno de los objetivos de C#10 es eliminar código de los archivos de código fuente de C#, simplificando su codificación y lectura. Lo hemos visto con la introducción de características como directivas using
globales o los using
implícitos: en ambos casos se ahorraba espacio en vertical sustituyendo los using
declarados individualmente en cada archivo por directivas aplicadas de forma global al proyecto, bien de forma explícita o implícita.
En cambio, los espacios de nombre con ámbito de archivo o namespace declarations permiten ahorrar espacio en horizontal, evitando un nivel de indentación en el código que la mayoría de las veces es innecesario.

Hace unos días hablábamos de las directivas using
globales, un interesante añadido a C# 10 que permite importar espacios de nombres en todos los archivos de código del proyecto, sin necesidad de repetir cientos de veces las mismas líneas en sus encabezados. Simplemente, si un namespace es interesante para nuestro proyecto, lo declaramos como global en algún punto y será lo mismo que si lo hubiéramos hecho en cada uno de los archivos .cs:
global using System;
global using System.Text;
global using System.Text.Json;
global using MyProject.Model;
...
Bien podían haberlo dejado aquí porque ya es una mejora sustancial respecto a lo que tenemos, pero no, el equipo de diseño de C# sigue introduciendo detalles que pueden hacernos la vida más sencilla. Es el caso de los implicit usings que, de la misma forma, acompañan a .NET 6 y C# 10.
Seguro que estáis acostumbrados a ver y escribir las, a veces extensas, listas de directivas
using
encabezando vuestros archivos de código fuente C#. Aunque ciertamente los entornos de desarrollo actuales son de bastante ayuda a la hora de introducirlos e incluso a veces nos permiten colapsarlos, son unos grandes consumidores del valioso espacio vertical de nuestros monitores:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// ... (muchos using más)
namespace MyApplication
{
public class MyClass
{
...
}
}
Pero si habéis trabajado con Razor, ya sea para crear vistas MVC/Razor Pages o bien desde Blazor, seguro que os habrán encantado los archivos tipo _ViewImports.cshtml
o _Imports.razor
, pues permiten introducir directivas que se apliquen a todos los archivos Razor del proyecto.
¿No sería buena idea llevar esto mismo a nivel del lenguaje?

Me encanta que el lenguaje C# vaya introduciendo características que consiguen que cada vez tengamos que escribir menos para conseguir lo mismo, y, sobre todo, si la legibilidad posterior del código no se ve comprometida.
Uno de estos casos son los recientes target-typed new expressions, o expresiones new con el tipo del destino, que básicamente permite evitar la introducción del tipo de datos al usar el constructor de una clase, siempre que el compilador sea capaz de inferirlo por su contexto.
Vamos a echarle un vistazo en este post.

Desde C# 7 podemos emplear patrones en expresiones is
o bloques switch
para especificar las condiciones que deseamos comprobar, y cada nueva versión del lenguaje sigue introduciendo novedades al pattern matching, haciéndolo cada vez más sencillo y cómodo de utilizar.
En particular, C# 9 ha añadido un montón de características interesantes destinadas a facilitar el uso de patrones, pero en este post vamos a centrarnos en las dos más importantes: los combinadores de patrones y los patrones relacionales.

Hace algunos años hablábamos de que la forma más correcta de determinar si un objeto es nulo en C# era utilizando el operador is
:
var invoice = _invoiceRepository.GetById(18);
if(invoice is null)
{
// Hacer algo
}
Como vimos en su momento, esta opción era mejor que utilizar una comparación directa como invoice == null
porque el operador de igualdad podía ser sobrecargado y, por tanto, su comportamiento podría ser modificado, mientras que el operador is
no es sobrecargable.
Sin embargo, al comenzar al usar esta fórmula, encontrábamos un pequeño inconveniente cuando queríamos determinar justo lo contrario, es decir, saber cuándo un objeto no es nulo, pues la sintaxis se volvía algo más pesada:
var invoice = _invoiceRepository.GetById(18);
if(!(invoice is null))
{
// Hacer algo
}