Null-условное присваивание в C# 14: использование ?. и ?[] в левой части
C# 14 расширяет null-условные операторы, позволяя использовать их в левой части присваиваний и устраняя многословные проверки на null при установке свойств или индексаторов.
C# 14 приносит небольшое, но значимое изменение: null-условные операторы ?. и ?[] теперь работают в левой части присваиваний. Это устраняет распространённый шаблон обёртывания присваиваний свойств в проверки на null.
Какой многословный шаблон он заменяет
До C# 14 присваивание свойству только тогда, когда объект не равен null, требовало явных проверок:
if (customer is not null)
{
customer.LastOrderDate = DateTime.UtcNow;
}
if (settings is not null)
{
settings["theme"] = "dark";
}
С глубоко вложенными объектами становилось ещё хуже:
if (order?.Customer?.Address is not null)
{
order.Customer.Address.IsVerified = true;
}
Null-условное присваивание в C# 14
C# 14 позволяет писать ту же логику более лаконично:
customer?.LastOrderDate = DateTime.UtcNow;
settings?["theme"] = "dark";
order?.Customer?.Address?.IsVerified = true;
Присваивание выполняется только в том случае, если левая часть вычисляется в ненулевую ссылку. Правая часть никогда не вычисляется, когда цель равна null.
Как это работает
Выражение P?.A = B эквивалентно:
if (P is not null)
{
P.A = B;
}
С одним важным отличием: P вычисляется только один раз. Это имеет значение, когда P представляет собой вызов метода или имеет побочные эффекты.
Составные операторы присваивания
Null-условное присваивание также работает с составными операторами, такими как +=, -=, *= и другими:
inventory?.StockLevel += restockAmount;
counter?.Value -= 1;
account?.Balance *= interestRate;
Каждое из этих выражений вычисляет левую часть один раз и применяет операцию только в том случае, если цель не равна null.
Инкремент и декремент не разрешены
Одно ограничение: операторы ++ и -- нельзя использовать с null-условным присваиванием. Этот код не скомпилируется:
// Error: ++ and -- not allowed
counter?.Value++;
Используйте составное присваивание вместо этого:
counter?.Value += 1;
Практический пример: обработчики событий
Распространённый случай использования - условная установка обработчиков событий:
public void Initialize(Button? submitButton, Button? cancelButton)
{
submitButton?.Click += OnSubmit;
cancelButton?.Click += OnCancel;
}
Без null-условного присваивания вам потребовались бы отдельные проверки на null для каждой кнопки.
Цепочки с индексаторами
Оператор ?[] работает таким же образом для присваиваний через индексатор:
Dictionary<string, string>? headers = GetHeaders();
headers?["Authorization"] = $"Bearer {token}";
headers?["Content-Type"] = "application/json";
Если headers равен null, ни одно из присваиваний не выполняется и исключение не выбрасывается.
Когда это использовать
Null-условное присваивание лучше всего подходит, когда:
- У вас есть необязательные объекты, которые могут нуждаться, а могут и не нуждаться в обновлениях
- Вы работаете со ссылочными типами, допускающими null, и хотите избежать многословных проверок на null
- Присваивание представляет собой операцию fire-and-forget, при которой вам не нужно знать, было ли оно выполнено
Возможность доступна в .NET 10 с C# 14. Установите <LangVersion>14</LangVersion> в файле проекта, чтобы её включить.
Полную спецификацию смотрите в разделе Null-условное присваивание на Microsoft Learn.
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.