Отмена и шаблон отмены

Tip

Эта статья является частью раздела "Основы" для разработчиков , которые уже знают хотя бы один язык программирования и учат C#. Если вы не знакомы с шаблонами, начните с обзора сопоставления шаблонов. Полный синтаксис см. в справочнике по шаблону discard.

Маркер подчеркивания (_) сообщает, что значение не требуется. Его точное значение зависит от того, где он отображается:

Context Значение _
Ветвь switch-выражения или вложенный шаблон Шаблон отбрасывания, который сопоставляется без сохранения результата
Деконструкция или out аргумент Отмена, которая игнорирует одно создаваемое значение
Назначение, например _ = expression Присваивание с отбрасыванием результата, которое вычисляет выражение и игнорирует его результат
Два или более лямбда-параметров с именем _ Отмена параметров , входные данные которых не используются
var _ в шаблоне var Шаблон с обозначением отбрасывания

Эти формы используют орфографию и намерение, но они не взаимозаменяемы.

Сопоставление шаблонов с switch

В следующем примере statusCode — это int. Каждый рычаг переключателя генерирует сообщение string, которое программа выводит в консоль. Окончательный _ обрабатывает каждый код состояния, отличный от 200 и 404:

static void ShowStatus()
{
    int statusCode = 503;
    string message = statusCode switch
    {
        200 => "Ready",
        404 => "Not found",
        _ => "Another status"
    };

    Console.WriteLine(message);
}

Шаблон отбрасывания применяется к входному выражению. C# вычисляет выражение, и _ соответствует вычисленному значению, не захватывая его. Выберите _ в качестве последней ветви switch-выражения, если для всех значений, не обработанных ранее, должен использоваться один и тот же вариант по умолчанию. Поместите его последним, поскольку оно совпадает со всем, включая null.

Форма var _ является шаблоном var с обозначением отбрасывания. Он также соответствует каждому вычисляемому значению, но он не вводит удобочитаемую переменную. Предпочитайте более короткий _ шаблон отбрасывания для случая switch, охватывающего все остальные значения. Дополнительные сведения о шаблонах и обозначениях см. в var разделе "Объявление", "Константы" и var "Шаблоны".

Объявления о деконструкции

GetForecast возвращает кортеж из четырёх компонентов: город string и три значения int для максимальной температуры, минимальной температуры и вероятности дождя. Объявление деконструкции сохраняет city и high потому, что программа отображает их. Для низкой температуры и вероятности дождя используется _, так как если дать имена этим неиспользуемым компонентам, это будет означать, что они нужны коду:

static void ShowForecast()
{
    var (city, high, _, _) = GetForecast();
    Console.WriteLine($"{city}: high {high}°C");

    static (string City, int High, int Low, int RainChance) GetForecast() =>
        ("Portland", 18, 9, 40);
}

Тот же синтаксис отбрасывания работает, если метод объекта Deconstruct возвращает несколько значений. Сведения о них см. в разделе «Деконструкция кортежей и других типов».

Вызовы методов с out параметрами

Предположим, поле ввода принимает текст только в том случае, если он представляет целое число. Метод TryParse(String, Int32) возвращает значение bool , указывающее, выполнен ли синтаксический анализ. Он также возвращает разобранный int через параметр out. Следующему коду требуется только логический результат, чтобы принять или отклонить ввод:

static void CheckInput()
{
    string text = "42";

    if (IsWholeNumber(text))
    {
        Console.WriteLine($"Accepted: {text}");
    }
    else
    {
        Console.WriteLine("Enter a whole number.");
    }

    static bool IsWholeNumber(string text) => int.TryParse(text, out _);
}

Используйте out _ только в случае успеха операции. Отбрасывание явно показывает, что разобранное число не нужно. Если позже коду нужен номер, присвойте out аргументу имя, например out int number, и сохраните это значение.

Присваивание с отбрасыванием, _ = expression, вычисляет выражение и намеренно игнорирует его результат. Иногда это бывает полезно, когда выражение в противном случае не является допустимой инструкцией.

Это важно

Не используйте _ = Task.Run(...) или _ = SomeAsyncMethod(), чтобы отбрасывать задачу в коде приложения. Дождите задачу, чтобы ее завершение и исключения оставались в потоке вызовов. Присваивание в discard не делает задачу безопасной, не отслеживает ее исключение и не создает поддерживаемую операцию «запустить и забыть».

Пометка неиспользуемых лямбда-параметров

object? Получает EventHandler отправителя и EventArgs значение. Для следующего обработчика не нужен ни один из этих параметров; он лишь выводит "Timer tick" в консоль. Именование обоих параметров _ делает их неиспользуемое состояние видимым без изобретания имен, которые тело никогда не использует:

static void ShowLambdaDiscards()
{
    EventHandler handler = (_, _) => Console.WriteLine("Timer tick");
    handler(null, EventArgs.Empty);
}

Выберите отбрасываемые параметры, если сигнатура делегата требует входные параметры, которые не используются в теле лямбда-выражения. Если лямбда-файл имеет только один параметр с именем _, _ остается обычным именем параметра для обратной совместимости.

Избегайте _ в качестве идентификатора

_ может быть обычным идентификатором в тех контекстах, где C# не распознает его как отбрасываемое значение. Переменной, находящейся в области видимости и имеющей имя _, можно присвоить значение выражением, которое выглядит как присваивание отбрасыванию. В контексте сопоставления с образцом доступная константа или тип с именем _ также может изменить интерпретацию _. Избегайте объявления собственных переменных, констант или типов с именем _; используйте _, чтобы указать, что значение намеренно отбрасывается.

См. также