_ => що означає це підкреслення у виразах лямбда?


111

Що означає вираз лямбда _=> expr?

Яка мета _введення в лямбду?

Приклад:

int count = 0;
list.ForEach(_ => count += 1);

8
Привіт і ласкаво просимо до StackOverflow. Я зважився трохи відредагувати ваше запитання, щоб збільшити ваші шанси отримати корисні відповіді, сподіваюся, ви не заперечуєте.
Лассе В. Карлсен

Слід зазначити , що, припускаючи listце IEnumerable<T>, вони можуть (і повинні) тільки що використовувалиsum = list.Count();
BlueRaja - Денні Pflughoeft

Я думаю, це може бути використане для запобігання "забрудненню" області застосування новим ім'ям змінної, яке може бути використане десь в іншому місці, що може спричинити конфлікт.
Тім Шмелтер

Відповіді:


84

Це умова, яка використовується, коли вам не байдуже параметр.


3
Він частіше зустрічається в Haskell та інших функціональних мовах. Я думаю, що звідси воно походить.
Гейб Мутхарт

10
У Haskell, ML, Scala та інших _є символом підстановки у відповідності зразком. Це в основному означає "Мені все одно, я завжди хочу, щоб це відповідало". Це "мені байдуже" потім переноситься, коли йдеться про іменування речей, які вас не цікавлять, і звідти воно переливається на інші мови програмування. Наприклад, він також використовується в Ruby для того, щоб означати те саме, що і в цьому прикладі, хоча _він не має особливого значення в Ruby.
Йорг W Міттаг

@ JörgWMittag Правда в травні 2010 року, але не станом на червень 2010 року. Дивовижні терміни! :) stackoverflow.com/q/6397078/38765
Андрій Грімм

38

Це ім'я параметра, хоч і не корисне, але це правило, яке зазвичай використовується (за деякими умовами), коли вам потрібно вказати, що вираз має параметр для того, щоб отримати компіляцію коду, але вам насправді все одно про це, так що ви просто збираєтесь ігнорувати це.

Це в основному використання синтаксису для того, що становить юридичний ідентифікатор у C #, і оскільки ідентифікатор може починатися з підкреслення і нічого більше не містити, це просто ім'я параметра.

Ви могли просто легко написати:

var _ = 10;

1
Замість _ чи можемо ми використовувати ()?
amesh

2
Ви спробували скористатися цим?
Лассе В. Карлсен

Так, я використовував це, коли створював нитку, використовуючи лямбда-вираз. Thread t= new Thread(()=>doSomething(x,y)); t.start();
amesh

Я припускаю, що використання _ передає кожну змінну колекції до виразу лямбда, навіть якщо вона не використовується. Але коли ми використовуємо (), це може не статися. Я маю на увазі параметр менше лямбда.
amesh

Потрібно спробувати це за допомогою виклику методу ForEach. У конструкторі Thread є перевантаження, яка приймає делегата, який не приймає жодних параметрів. Спробуйте викликати такий метод, як, наприклад, ForEach, який замість цього приймає делегата, який приймає параметр.
Лассе В. Карлсен


10

Оскільки вираз lamda використовується в основному в короткому, анонімному коді, так що ім'я змінної іноді не є необхідним, навіть вони не використовують змінну в кодовому блоці, так що вони просто дають _ для короткого конвенції


7

Я також друге використання _ => _.method()для однорядкових, методів виклику лямбда, оскільки це зменшує пізнавальну вагу інструкції. Спеціально, використовуючи дженерики, написання x => x.method()просто додає роздуму "Що це" х "? Це координата в просторі?".

Розглянемо наступний випадок:

Initialize<Client> ( _=>_.Init() );

Використовується для виклику Generics, підкреслення в цьому випадку працює як "обхідний символ". Це дозволяє уникнути надмірності, визначаючи, що тип аргументу очевидний і його можна заразити від використання - так само, як коли ви використовуєте 'var', щоб запобігти повторенню декларації типу. Писання client=>client.Init()тут просто збільшило б інструкцію, не додаючи їй жодного значення.

Очевидно, це не стосується параметрів, що передаються методу, який повинен бути названий описово. Напр .:Do( id=>Log(id) );

Використання єдиного підкреслення параметрів для викликів методів навряд чи виправдане при використанні блоку коду замість однолінійного, оскільки ідентифікатор лямбда відключається від свого загального визначення. Загалом, коли той самий ідентифікатор потрібно використовувати повторно, дайте йому описову назву.

Суть полягає в тому, що багатослівність виправдана лише для неоднозначностей, особливо для лямбда, які були створені в першу чергу для спрощення створення анонімних делегатів. У будь-якому випадку слід використовувати здоровий глузд, врівноважуючи розбірливість і стислість. Якщо символ є лише «гачком» для реальної функціональності, один ідентифікатор символів ідеально підходить. Так буває з циклами For-циклів та літерами "i" та "j" як індексаторами.


2
+1 для цього підходу! Я хоч і був єдиним, хто використовував підкреслення в лямбдах, щоб "зменшити пізнавальну вагу", а не для того, щоб показати, що цей параметр не використовується. Зчиснення підкреслення стає легше читати, особливо якщо ланцюг багато, і ви можете негайно зробити висновок про тип, як це часто буває з LINQ-запитами!
Варвара Калініна

3
Do(id => Log(id))краще скорочено як Do(Log).
Алуан Хаддад
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.