! — оператор (допускающий значение NULL) (справочник по C#)
Унарный оператор постфикса !
— это оператор null-forgiving, или null-подавление. В контексте заметки с включенным значением NULL используется оператор null-forgiving для подавления всех предупреждений, допускающих значение NULL для предыдущего выражения. Унарный префиксный оператор !
является оператором логического отрицания. Оператор, допускающий NULL, ни на что не влияет во время выполнения. Он влияет только на статический анализ потока компилятора путем изменения состояния NULL выражения. Во время выполнения выражение x!
сравнивается с результатом базового выражения x
.
Дополнительные сведения о ссылочных типах, допускающих значения NULL, см. в разделе Ссылочные типы, допускающие значение NULL.
Примеры
Один из вариантов использования оператора, допускающего значение NULL, — тестирование логики проверки аргументов. Например, рассмотрим следующий класс.
#nullable enable
public class Person
{
public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));
public string Name { get; }
}
С помощью платформы тестирования MSTest можно создать следующий тест для логики проверки в конструкторе:
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void NullNameShouldThrowTest()
{
var person = new Person(null!);
}
Без оператора, допускающего значение NULL, компилятор создает следующее предупреждение для предыдущего кода: Warning CS8625: Cannot convert null literal to non-nullable reference type
. Используя оператор, допускающий значение NULL, вы сообщаете компилятору, что передача null
ожидается и что о ней не нужно предупреждать.
Вы также можете использовать оператор с прощения null, если определенно известно, что выражение не может быть null
, но компилятор не может распознать это. В следующем примере, если IsValid
метод возвращает, его аргумент не null
является true
и его можно безопасно разыменовать:
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;
Без оператора, допускающего значение NULL, компилятор создает следующее предупреждение для кода p.Name
: Warning CS8602: Dereference of a possibly null reference
.
Если метод можно изменить IsValid
, можно использовать атрибут NotNullWhen для информирования компилятора о том, что аргумент IsValid
метода не может быть при null
возврате 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;
В предыдущем примере не требуется использовать оператор с прощания null, так как компилятор имеет достаточно сведений, чтобы узнать, что p
не может находиться null
внутри инструкции if
. См. сведения об атрибутах, позволяющих указать дополнительную информацию о состоянии NULL для переменной, в руководстве по включению в API атрибутов для определения ожидаемых значений NULL.
Спецификация языка C#
См. сведения об операторе, допускающем значение NULL, в черновике спецификации по ссылочным типам допускающим значение NULL.