! (permite valores NULL) (referencia de C#)

Disponible en C# 8.0 y versiones posteriores, el operador ! de postfijo unario es el operador que permite valores NULL o supresión de valores NULL. En un contexto de anotación que admite un valor NULL habilitado, se usa el operador que permite un valor NULL para declarar que la expresión x de un tipo de referencia no es null: x!. El operador ! de prefijo unario es el operador lógico de negación.

El operador que permite un valor NULL no tiene ningún efecto en tiempo de ejecución. Solo afecta al análisis de flujo estático del compilador al cambiar el estado NULL de la expresión. En tiempo de ejecución, la expresión x! se evalúa en el resultado de la expresión subyacente x.

Para obtener más información sobre la característica de tipos de referencia que admiten un valor NULL, consulte Tipos de referencia que admiten un valor NULL.

Ejemplos

Uno de los casos de uso del operador que permite un valor NULL es probar la lógica de validación de argumentos. Por ejemplo, considere la siguiente clase:

#nullable enable
public class Person
{
    public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));

    public string Name { get; }
}

Con el marco de pruebas MSTest puede crear la prueba siguiente para la lógica de validación en el constructor:

[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void NullNameShouldThrowTest()
{
    var person = new Person(null!);
}

Sin el operador que permite un valor NULL, el compilador genera la advertencia siguiente para el código anterior: Warning CS8625: Cannot convert null literal to non-nullable reference type. Al usar el operador que permite un valor NULL, se notifica al compilador que lo esperado es que se pase null y no se debe advertir al respecto.

También puede usar el operador que permite valores NULL cuando sepa a ciencia cierta que una expresión no puede ser null, pero el compilador no consigue reconocerlo. En el ejemplo siguiente, si el método IsValid devuelve true, su argumento no es null y puede desreferenciarlo de forma segura:

public static void Main()
{
    Person? p = Find("John");
    if (IsValid(p))
    {
        Console.WriteLine($"Found {p!.Name}");
    }
}

public static bool IsValid(Person? person)
    => person is not null && person.Name is not null;

Sin el operador que permite un valor NULL, el compilador genera la advertencia siguiente para el código p.Name: Warning CS8602: Dereference of a possibly null reference.

Si puede modificar el método IsValid, puede usar el atributo NotNullWhen para notificar al compilador que un argumento del método IsValid no puede ser null cuando el método devuelve true:

public static void Main()
{
    Person? p = Find("John");
    if (IsValid(p))
    {
        Console.WriteLine($"Found {p.Name}");
    }
}

public static bool IsValid([NotNullWhen(true)] Person? person)
    => person is not null && person.Name is not null;

En el ejemplo anterior, no es necesario usar el operador que permite un valor NULL porque el compilador tiene suficiente información para averiguar que p no puede ser null en la instrucción if. Para más información sobre los atributos que permiten proporcionar información adicional sobre el estado NULL de una variable, vea Actualización de las API con atributos para definir las expectativas NULL.

Especificación del lenguaje C#

Para obtener más información, consulte la sección The null-forgiving operator (El operador que admite valores NULL) del borrador de la especificación de tipos de referencia que aceptan valores NULL.

Vea también