Ключом к пониманию того, что означает null!
, является понимание оператора !
.Возможно, вы использовали его раньше как оператор «не».Но начиная с C # 8.0 оператор также может использоваться в типе для управления Nullabilty
Что такое оператор !
при использовании в типе?
Оператор !
, когда используетсядля типа, называется оператором Null Forgiving [ docs ].Он был введен в C # 8.0
Техническое объяснение
Типичное использование
Принимая это определение:
class Person
{
public string? MiddleName;
}
Использование будет:
void LogPerson(Person person)
{
Console.WriteLine(person.MiddleName.Length); // WARNING: may be null
Console.WriteLine(person.MiddleName!.Length); // No warning
}
Этот оператор в основном отключает нулевые проверки компилятора.
Внутренняя работа
Использование этого оператора сообщает компилятору, что к чему-то, что может быть нулевым, безопасно обращаться,Вы выражаете намерение «не заботиться» о нулевой безопасности в этом случае.
Есть два состояния, в которых может находиться переменная - когда речь идет о нулевой безопасности.
- Nullable - Может быть нулевым.
- Не обнуляется - Не может быть нулевым.
Начиная с C # 8.0 все ссылочные типы не обнуляются.по умолчанию.
«Обнуляемость» может быть изменена этими двумя новыми операторами типов:
!
= От Nullable
до Non-Nullable
?
= От Non-Nullable
до Nullable
Эти операторы в основном аналогичны друг другу.Компилятор использует информацию, которую вы определяете с этими операторами, для обеспечения нулевой безопасности.
?
Использование оператора.
Nullable string? x;
x
является ссылочным типом - поэтому по умолчанию не обнуляется. - Мы применяем оператор
?
- что делает его обнуляемым. x = null
Работает нормально.
Не обнуляемый string y;
y
является ссылочным типом - поэтому по умолчанию не обнуляется. y = null
Создает предупреждение, поскольку вы назначаете нулевое значение чему-то, что не должно быть нулевым.
!
Использование оператора.
string x;
string? y = null;
x = y
- Незаконно!-
Warning: "y" may be null
- Левая сторона задания не допускает обнуления, но правая сторона обнуляется.
x = y!
- Legal!
- Правая и левая части присвоения не могут быть обнулены.
- Работает с
y!
Применяет оператор !
к y
, что делает его не-nullable.
ПРЕДУПРЕЖДЕНИЕ Оператор !
отключает проверки компилятора только на уровне системы типов - во время выполнения,значение все еще может быть нулевым.
Это анти-шаблон.
Вы должны попробовать до избегать , используя !
Null-Forgiving-Operator.
Существуют допустимые варианты использования (подробно описанные ниже), такие как модульные тесты, в которых этот оператор подходит для использования.Тем не менее, в 99% случаев вам лучше найти альтернативное решение.Пожалуйста, не добавляйте десятки !
в ваш код, просто чтобы замолчать предупреждения.Подумайте, действительно ли ваше дело оправдывает использование.
Используйте - но с осторожностью.Если нет конкретной цели / варианта использования, предпочитайте не использовать его.
Это сводит на нет эффекты нулевой безопасности, которые вы гарантируете компилятором.
Использованиеоператор !
будет очень трудно находить ошибки. Если у вас есть свойство, помеченное как необнуляемое, вы можете использовать его безопасно.Но во время выполнения вы неожиданно сталкиваетесь с NullReferenceException
и чесаете голову.Поскольку значение фактически становится нулевым после обхода проверок компилятором с помощью !
.
Почему тогда существует этот оператор?
- В некоторых крайних случаях компилятор не можетобнаружить, что значение NULL может быть ненулевым.
- Упрощенная миграция унаследованного кода.
- В некоторых случаях вам просто все равно, станет ли что-либо пустым.
- При работе с юнит-тестами вы можете проверить поведение кода, когда
null
проходит.
Отвечая конкретно на ваш вопрос.
Итакчто означает null!
Он сообщает компилятору, что null
не является значением null
.Звучит странно, не правда ли?
Это то же самое, что и y!
из приведенного выше примера. Это выглядит странно, так как вы применяете оператор к null
литерал .Но концепция та же.
Разбирая происходящее.
public string LastName { get; } = null!;
Эта строка определяет свойство класса, не допускающее обнуления, с именем LastName
типа string
.Поскольку он не обнуляем, вы технически не можете присвоить ему значение null - очевидно.
Но вы просто делаете это - назначаете null
на LastName
- используя оператор !
.Потому что null!
не равен нулю - поскольку компилятор обеспокоен нулевой безопасностью.