Referencias anulables en C# 8.0 y posteriores (IV): el operador ! y las propiedades anulables

“Will you decide what makes you an entity
That’s your identity”
Black Sabbath, “End of the Beginning” (2013)

Después de una pausa que se ha extendido más de lo esperado, dedico hoy un último post al operador ! (null-forgiving operator), sobre el que ya hablamos aquí y aquí. Esta vez quiero presentar otro escenario en el que este operador es de utilidad, con el que me topé recientemente experimentando con Entity Framework para un nuevo pequeño proyecto. El ejemplo que se presenta aquí se basa en un proyecto de aplicación de consola para .NET 5.0 (puesto que necesitamos C# 8 para las referencias anulables), que utiliza el paquete Entity Framework Core 5.0.6 para acceder a un clone de una base de datos a la que tengo mucho cariño: la base de datos FUTBOL2006 que se utiliza en mi libro «C# 3.0 y LINQ».

Las herramientas de Entity Framework Core 5 saben cómo interpretar las referencias anulables que el programador incluya en las definiciones code-first de las entidades:

01  public class Futbolista
02  {
03      public int Id { get; set; }
04      public string Nombre { get; set; } // NOT NULL en el SQL generado
05      public DateTime? FechaNacimiento { get; set; }
06      public string? LugarNacimiento { get; set; } // NULL en el SQL generado
07      public char Posicion { get; set; }
08      public virtual Club Club { get; set; } // propiedad de navegación del modelo
09  }

Al compilar el proyecto, para esta clase se obtienen dos advertencias en las líneas 04 (que corresponde a una propiedad física de la tabla) y 08 (que corresponde a una propiedad de navegación):

CS8618: Non-nullable property must contain a non-null value when exiting constructor.
        Consider declaring the property as nullable.

Por supuesto, la sugerencia de declarar las propiedades como anulables iría en contra de lo que intentamos expresar en primer lugar. En esta página de Microsoft se hace un análisis del problema y se ofrecen posibles alternativas. Una de esas alternativas es precisamente inicializar esas propiedades a null (un valor que nunca se observaría en la vida real) y utilizar el operador ! para acallar al compilador:

04      public string Nombre { get; set; } = null!;

Para terminar, presento a continuación un pequeño programa basado en el modelo anterior que lista los futbolistas que jugaron en la temporada 2006 en el Atlético de Madrid:

static void Main(string[] args)
{
    using var context = new Futbol2006Context();

    // Mostrar futbolistas del Atleti
    var colchoneros2006 = context.Futbolistas.
        Where(f => f.Club.Codigo == "ATM").
        OrderBy(f => f.Posicion).
        ThenBy(f => f.Nombre);

    foreach (var f in colchoneros2006)
    {
        Console.WriteLine("{0} ({1})", f.Nombre, f.Posicion);
    }
}

Ésta es la salida que produce el programa. ¡Cuánto tiempo ha pasado!

ANTONIO LOPEZ (D)
FABIANO ELLER (D)
PABLO (D)
PEREA (D)
PERNIA (D)
SEITARIDIS (D)
ZE CASTRO (D)
AGÜERO (L)
MAXI (L)
MISTA (L)
PETROV (L)
TORRES (L)
COSTINHA (M)
DE LAS CUEVAS (M)
GABI (M)
GALLETTI (M)
JURADO (M)
LUCCIN (M)
MANICHE (M)
VALERA (M)
IVAN CUELLAR (P)
LEO FRANCO (P)

Referencia musical: Black Sabbath ocupa sin lugar a dudas un lugar destacado entre los pioneros del rock y el heavy metal. Aunque luego dejé de oírlos y me decanté por una línea más melódica y espiritual del rock, de adolescente sus discos «Black Sabbath» y «Paranoid» (ambos de un lejano 1970) me impresionaron bastante. El tema «End of the Beginning» (Is this the end of the beginning, or the beginning of the end?) pertenece al último disco de estudio que sacaron, «13» (2013), con el que tal vez paradójicamente llegaron al tope de las listas de éxitos por primera vez.

Octavio Hernandez

Desarrollador y consultor en tecnologías .NET. Microsoft C# MVP entre 2004 y 2010.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *