Entendiendo default! en los parámetros

Carlos BCCarlos BC
4 min read

En el desarrollo con Blazor WASM, una de las tareas más comunes es pasar datos desde un componente padre a un hijo mediante propiedades con [Parameter]. Al declarar esas propiedades en los hijos, una pregunta que puede surgir es:

¿Cuál es la diferencia entre usar = default!; y new() o dejarlo sin inicializar?

En este artículo veremos la razón detrás del uso de default!, cuándo es correcto, por qué es importante en Blazor, y qué no se debería hacer si se quiere que el componente sea seguro y funcione como uno espera.

📦 [Parameter] en Blazor

En Blazor, una propiedad [Parameter] representa un valor que será asignado por el componente padre. Por ejemplo:

@code {
    [Parameter]
    public User User { get; set; }
}

Pero si se usa un código como el de arriba, el compilador de C# marcará un warning sobre posibles usos de null, ya que User no fue inicializado.

🔨 Usando default!

Para evitar el warning sin inicializar con un valor arbitrario, se usa:

[Parameter]
public User User { get; set; } = default!;

¿Qué significa default!?

  • default representa el valor por defecto del tipo (null para clases).

  • El ! es un operador de supresión de advertencia de nulabilidad.

En resumen: se le dice al compilador "sé que esto es null ahora, pero confía en que será asignado correctamente más adelante."

Esto no cambia el comportamiento en tiempo de ejecución, pero elimina el warning de compilación y mantiene el código limpio y seguro.

🧨 ¿Por qué no usar new()?

Se podría pensar: “¿Y si simplemente inicializo la propiedad?”

public User User { get; set; } = new User();

No hay que hacer esto

Esto rompe la lógica de Blazor. Si se hace esto:

  • El componente hijo tendrá su propia instancia de User.

  • Ya no usará la instancia que el padre le envió.

  • Las modificaciones que se hagan en el hijo no afectarán al padre, y viceversa.

🛡️ Agregando seguridad con [EditorRequired]

.NET 6 introdujo una gran ayuda: el atributo [EditorRequired].

[Parameter, EditorRequired]
public User User { get; set; } = default!;

¿Qué hace?

  • Obliga a que el parámetro sea pasado desde el componente padre.

  • Si uno se olvida agregar el parámetro, el editor (Visual Studio / VS Code) mostrará una advertencia clara.

Esto nos ayuda a evitar errores sutiles donde un componente se renderiza pero su parámetro vital nunca se asignó.

🚫 ¿Y required de C# 11?

Desde C# 11, contamos con el modificador required, que permite marcar propiedades que deben ser inicializadas obligatoriamente al momento de crear un objeto, ya sea mediante constructor o inicialización por objeto:

public required User User { get; set; }

Pero en Blazor:

required NO funciona como se espera en componentes.

  • Blazor crea las instancias de los componentes y luego les asigna los parámetros.

  • Eso no cumple con los requisitos del compilador para required, y no verás advertencias útiles.

¿Por qué no funciona como creemos?

El ciclo de vida de los componentes en Blazor funciona de la siguiente manera:

  1. El framework crea una instancia del componente utilizando su constructor por defecto.

  2. Luego, Blazor asigna los valores de los parámetros [Parameter] mediante reflection.

Este proceso va en contra de cómo espera funcionar required, que necesita que las propiedades obligatorias sean establecidas durante la creación del objeto. Como resultado, el compilador no puede verificar si una propiedad required fue realmente inicializada, y no se generarán advertencias útiles.

¿Qué implica esto?

  • No se reciben advertencias si olvidamos establecer el parámetro desde el componente padre.

  • Existe el riesgo de que la propiedad quede sin asignar en tiempo de ejecución, generando errores difíciles de detectar.

¿Cuál es la alternativa correcta?

En el caso de Blazor, debemos usar:

[Parameter, EditorRequired]
public User User { get; set; } = default!;

Esto sí se integra correctamente con el ciclo de vida del componente y:

  • Nos alerta en tiempo de compilación si el parámetro no fue provisto.

  • Funciona como un contrato explícito para otros desarrolladores.

  • Es la práctica recomendada para trabajar con parámetros obligatorios en Blazor.

✍️ Conclusiones

✅ Usar = default! para evitar warnings y dejar que Blazor haga su trabajo.
✅ Usar [EditorRequired] si el parámetro es obligatorio.
❌ No usar new() si se espera recibir una instancia desde el padre.
❌ Evitar required en componentes Blazor, no funciona como parece o como uno esperaría.

0
Subscribe to my newsletter

Read articles from Carlos BC directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Carlos BC
Carlos BC

Diseñador gráfico e ingeniero informático dedicado al desarrollo de software. Me considero un entusiasta del código y todo lo que tiene que ver con él, por lo mismo estoy en una constante búsqueda de conocimiento para ser un mejor programador.En el día a día suelo trabajar como fullstack, pero suelo tender más al frontend, actualmente trabajo con .net y blazor.