! ! (tolerante a nulo) operador (referência do C#)
O operador !
de sufixo unário é o operador tolerante a nulo ou de supressão de nulo. Em um contexto de anotação nulo habilitado, você usa o operador de tolerância nula para suprimir todos os avisos anuláveis para a expressão anterior. O operador !
de prefixo unário é o operador de negação lógica. O operador tolerante a nulo não tem efeito em tempo de execução. Ele afeta apenas a análise de fluxo estático do compilador alterando o estado nulo da expressão. Em tempo de execução, a expressão x!
é avaliada como o resultado da expressão x
subjacente.
Para obter mais informações sobre o recurso de tipos de referência que permitem valor nulo, consulte Tipos de referência que permitem valor nulo.
Exemplos
Um dos casos de uso do operador tolerante a nulo está em testar a lógica de validação do argumento. Por exemplo, considere a seguinte classe:
#nullable enable
public class Person
{
public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));
public string Name { get; }
}
Usando a estrutura de teste MSTest, você pode criar o seguinte teste para a lógica de validação no construtor:
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void NullNameShouldThrowTest()
{
var person = new Person(null!);
}
Sem o operador tolerante a nulo, o compilador gera o seguinte aviso para o código anterior: Warning CS8625: Cannot convert null literal to non-nullable reference type
. Ao usar o operador tolerante a nulo, informe ao compilador que a passagem null
é esperada e não deve ser avisada.
Você também pode usar o operador de tolerância nula se souber definitivamente que uma expressão não pode ser null
, mas o compilador não consegue reconhecer isso. No exemplo a seguir, se o método IsValid
retornar true
, seu argumento não será null
e você poderá desreferenciá-lo com segurança:
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;
Sem o operador tolerante a nulo, o compilador gera o seguinte aviso para o código p.Name
: Warning CS8602: Dereference of a possibly null reference
.
Se você puder modificar o método IsValid
, poderá usar o atributo NotNullWhen para informar ao compilador que um argumento do método IsValid
não pode ser null
quando o método retornar 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;
No exemplo anterior, você não precisa usar o operador de tolerância nula porque o compilador tem informações suficientes para descobrir que p
não pode ser null
dentro da instrução if
. Para obter mais informações sobre os atributos que permitem fornecer informações adicionais sobre o estado nulo de uma variável, consulte As APIs de Atualização com atributos para definir expectativas quanto a nulos.
Especificação da linguagem C#
Para obter mais informações, consulte a seção Operador tolerante a nulo do Rascunho da especificação de tipos de referência que permitem valor nulo.