Что означает лямбда-выражение _=> expr
?
Какова цель использования _
лямбды?
Пример:
int count = 0;
list.ForEach(_ => count += 1);
list
это IEnumerable<T>
, они могут (и должны) только что использовалиsum = list.Count();
Что означает лямбда-выражение _=> expr
?
Какова цель использования _
лямбды?
Пример:
int count = 0;
list.ForEach(_ => count += 1);
list
это IEnumerable<T>
, они могут (и должны) только что использовалиsum = list.Count();
Ответы:
Это соглашение используется, когда вам не нужен параметр.
_
это подстановочный знак при сопоставлении с образцом. Это в основном означает: «Мне все равно, я всегда хочу, чтобы это совпадало». Это «мне все равно» затем переносится, когда дело доходит до наименования вещей, которые вам не нужны, и оттуда оно перетекает на другие языки программирования. Он, например, также используется в Ruby для обозначения того же значения, что и в этом примере, хотя _
в Ruby не имеет абсолютно никакого особого значения.
Это имя параметра, хотя и бесполезное, но оно обычно используется (по некоторым соглашениям), когда вам нужно указать, что выражение имеет параметр, чтобы код компилировался, но вам все равно об этом, так что вы просто проигнорируете это.
Он в основном использует синтаксис того, что представляет собой законный идентификатор в C #, и поскольку идентификатор может начинаться с подчеркивания и не содержать ничего другого, это просто имя параметра.
Вы могли бы легко написать:
var _ = 10;
Thread t= new Thread(()=>doSomething(x,y)); t.start();
_
- допустимое имя переменной. Они просто используются _
как переменные.
Я также поддерживаю использование _ => _.method()
однострочных лямбда-выражений с вызовом метода, поскольку это снижает когнитивный вес инструкции. Особенно при использовании обобщений письмо x => x.method()
просто добавляет долю секунды к вопросу «Что это за« x »? Это координата в пространстве?».
Рассмотрим следующий случай:
Initialize<Client> ( _=>_.Init() );
Используемый с вызовом Generics, подчеркивание в этом случае работает как «символ обхода». Он избегает избыточности, определяя, что тип аргумента очевиден и может быть получен из использования - точно так же, как когда вы используете 'var' для предотвращения повторения объявления типа. Написание client=>client.Init()
здесь просто сделало бы инструкцию длиннее, не добавляя к ней никакого смысла.
Очевидно, это не относится к параметрам, передаваемым в метод, который следует назвать описательно. Например.:Do( id=>Log(id) );
Использование одного параметра подчеркивания для вызовов методов вряд ли оправдано при использовании блока кода вместо однострочного, поскольку лямбда-идентификатор отключается от определения своего универсального типа. Обычно, когда один и тот же идентификатор должен использоваться повторно, дайте ему описательное имя.
Суть в том, что многословие оправдано только для устранения неоднозначности, особенно для лямбда-выражений, которые были созданы, в первую очередь, для упрощения создания анонимных делегатов. В любом случае следует руководствоваться здравым смыслом, сбалансировав разборчивость и лаконичность. Если символ является лишь «приманкой» к реальной функциональности, односимвольные идентификаторы вполне подойдут. Так обстоит дело с циклами For и буквами «i» и «j» в качестве индексаторов.
Do(id => Log(id))
лучше сокращать как Do(Log)
.