Start Debugging

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-условное присваивание лучше всего подходит, когда:

Возможность доступна в .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.

< Назад