Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1339. #ЗаметкиНаПолях Пустые Переменные в Лямбдах В твиттере задали интересный вопрос: Имеет ли смысл использование пустой переменной (дискарда) `_` в выражении типа?
( _ , args) =>{…}
Я ожидаю параметр, но не буду с ним ничего делать. — Layla #WomenOfDotNet (@LaylaCodesIt) Короткий ответ: да. Но кому нужны простые ответы? Пустые переменные появились в C# недавно. А это значит, что не всё так просто, как кажется. В C# есть несколько мест, где мы используем _ как пустую переменную. В примере ниже _ технически не является ей:
Func<int, int, int> f = (_, x) => 2 * x;

Лямбда здесь имеет два параметра, первый называется _, а второй называется x. C# принимает _ в качестве идентификатора в соответствии с правилами языка. Даже Visual Studio при наведении курсора на _ показывает подсказку «(parameter) int _». Мы можем продемонстрировать это, используя оба параметра:
Func<int, int, int> f2 = (_, x) => _ * x;

Следующий код не работал в C#8, но C#9 позволяет так писать:
Func<int, int, int> f3 = (_, _) => 42;

Здесь символы подчеркивания действительно являются пустыми переменными. (Правило состоит в том, что если лямбда имеет несколько параметров с именем _, то все они отбрасываются). A Visual Studio при наведении курсора на _ показывает подсказку «(discard) int _». Однако это работает только для лямбда-выражений. Зачем это нужно? Иногда мы вынуждены принимать аргументы, которые не будем использовать. Неиспользуемые параметры выглядят так, как будто это может быть ошибкой:
void ShowNumber(int i)
{
  Console.WriteLine(42);
}

Анализатор кода не выдаёт даже предупреждения, а выдаёт только сообщение IDE0060 уровня Message о неиспользуемой переменной. Однако читателю этого кода неочевидно, есть ли ошибка в коде метода или так и задумано. При этом, если вы фанат чистых сборок — без предупреждений и сообщений анализатора, — тогда изменения кода, приводящие к появлению новых сообщений, немедленно привлекут ваше внимание. Поэтому принято соглашение об использовании _ в качестве имени параметра, который бы намеренно игнорировался. Если вы измените предыдущий пример, переименовав параметр i в _, вы увидите, что компилятор перестанет выдавать сообщение IDE0060, поскольку он знает об этом соглашении:
void ShowNumber(int _)

Но, если у вас есть два параметра, которые вы хотите игнорировать:
void ShowNumber(int _, int _)
это вызовет ошибку компиляции CS0100 из-за дублирующего имени параметра _, т.к. пустые переменные можно использовать только в лямбдах. Использование _ - это просто соглашение. Это валидное имя для параметра, поэтому у нас не может быть двух параметров с именами _ по той же причине, по которой мы не можем иметь два параметра с именем i. Всё становится ещё интереснее, когда _ используется в качестве имени локальной переменной. Например, что, по-вашему, выведет код с картинки ниже в C#9+? Источник: https://endjin.com/blog/2022/09/csharp-lambda-discards