_ => apa arti garis bawah ini dalam ekspresi Lambda?

111

Apa arti ekspresi lambda _=> expr?

Apa tujuan _sebagai masukan bagi lambda?

Contoh:

int count = 0;
list.ForEach(_ => count += 1);
Prasad
sumber
8
Halo dan selamat datang di StackOverflow. Saya mengambil kebebasan mengedit pertanyaan Anda sedikit untuk meningkatkan kesempatan Anda mendapatkan jawaban yang berguna, harap Anda tidak keberatan.
Lasse V. Karlsen
Perhatikan bahwa, dengan asumsi listadalah IEnumerable<T>, mereka bisa (dan seharusnya) baru saja menggunakansum = list.Count();
BlueRaja - Danny Pflughoeft
Saya rasa ini dapat digunakan untuk mencegah Anda "mencemari" cakupan dengan nama variabel baru yang mungkin digunakan di tempat lain yang akan menyebabkan konflik.
Tim Schmelter

Jawaban:

84

Itu adalah konvensi yang digunakan saat Anda tidak peduli dengan parameternya.

ChaosPandion
sumber
3
Ini lebih umum di Haskell dan bahasa fungsional lainnya. Saya pikir dari sanalah asalnya.
Gabe Moothart
10
Di Haskell, ML, Scala dan lainnya, _adalah karakter wildcard dalam pencocokan pola. Ini pada dasarnya berarti "Saya tidak peduli, saya selalu ingin ini cocok". "Saya tidak peduli" ini kemudian terbawa ketika sampai pada penamaan hal-hal yang tidak Anda pedulikan dan dari sana, itu menyebar ke bahasa pemrograman lain. Ini, misalnya, juga digunakan di Ruby dengan arti yang sama seperti dalam contoh ini, meskipun _sama sekali tidak memiliki arti khusus di Ruby.
Jörg W Mittag
@ JörgWMittag True pada Mei 2010, tetapi tidak pada Juni 2010. Waktu yang mengagumkan! :) stackoverflow.com/q/6397078/38765
Andrew Grimm
38

Ini adalah nama parameter, meskipun bukan yang berguna, tetapi itu yang biasanya digunakan (oleh beberapa konvensi) ketika Anda perlu menentukan bahwa ekspresi memiliki parameter untuk mendapatkan kode untuk dikompilasi, tetapi Anda tidak terlalu peduli tentang itu, jadi Anda hanya akan mengabaikannya.

Ini pada dasarnya mengeksploitasi sintaks untuk apa yang merupakan pengenal hukum di C #, dan karena pengenal dapat dimulai dengan garis bawah, dan tidak berisi yang lain, itu hanya nama parameter.

Anda bisa saja dengan mudah menulis:

var _ = 10;
Lasse V. Karlsen
sumber
1
Daripada _, dapatkah kita menggunakan ()?
amesh
2
Apakah Anda mencoba menggunakan itu?
Lasse V. Karlsen
Ya, saya telah menggunakannya saat membuat utas menggunakan ekspresi lambda. Thread t= new Thread(()=>doSomething(x,y)); t.start();
amesh
Apa yang saya asumsikan adalah, penggunaan _ adalah meneruskan setiap variabel collection ke ekspresi lambda meskipun tidak digunakan. Tetapi ketika kita menggunakan () itu mungkin tidak terjadi. Maksud saya parameter kurang lambda.
amesh
Anda perlu mencobanya menggunakan panggilan metode ForEach. Ada kelebihan beban pada konstruktor Thread yang membutuhkan delegasi yang tidak mengambil parameter apa pun. Coba panggil metode, seperti ForEach itu, yang membutuhkan delegasi yang mengambil parameter.
Lasse V. Karlsen
29

_adalah nama variabel yang valid. Mereka hanya digunakan _sebagai variabel.

BlueRaja - Danny Pflughoeft
sumber
10

Karena ekspresi lamda banyak digunakan dalam bentuk kode yang pendek dan anonim sehingga nama variabel terkadang tidak diperlukan, bahkan tidak menggunakan variabel yang ada di blok kode, sehingga hanya memberikan _ singkatnya, konvensi

vodkhang.dll
sumber
7

Saya juga mendukung penggunaan _ => _.method()for one-line, method-call lambda, karena ini mengurangi bobot kognitif instruksi. Khususnya saat menggunakan obat generik, menulis x => x.method()hanya menambahkan pertimbangan sepersekian detik dari "Apa ini 'x'? Apakah itu koordinat dalam ruang?".

Pertimbangkan kasus berikut:

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

Digunakan dengan panggilan Generik, garis bawah dalam kasus ini berfungsi sebagai "simbol bypass". Ini menghindari redundansi, dengan mendefinisikan bahwa tipe argumen sudah jelas dan dapat disimpulkan dari penggunaan - sama seperti ketika Anda menggunakan 'var' untuk mencegah pengulangan deklarasi tipe. Menulis di client=>client.Init()sini hanya akan membuat instruksi lebih lama tanpa menambahkan makna apa pun padanya.

Jelas, ini tidak berlaku untuk parameter yang akan diteruskan ke metode, yang harus dinamai secara deskriptif. Misalnya.:Do( id=>Log(id) );

Penggunaan parameter garis bawah tunggal untuk panggilan metode hampir tidak dapat dibenarkan saat menggunakan blok kode sebagai ganti satu baris, karena pengenal lambda terputus dari definisi generiknya. Secara umum, jika pengenal yang sama akan digunakan kembali, berikan nama deskriptif.

Intinya adalah verbositas hanya dapat dibenarkan untuk disambiguasi, terutama untuk lambda, yang dibuat untuk menyederhanakan pembuatan delegasi anonim di tempat pertama. Bagaimanapun, akal sehat harus digunakan, menyeimbangkan keterbacaan dan keringkasan. Jika simbol hanya "pengait" ke fungsi sebenarnya, satu pengenal karakter sudah cukup. Itulah yang terjadi pada For-loops dan huruf "i" dan "j" sebagai pengindeks.

MaDDoX
sumber
2
1 untuk pendekatan ini! Saya pikir saya adalah satu-satunya yang menggunakan garis bawah di lambda untuk "mengurangi bobot kognitif" dan bukan untuk menunjukkan bahwa parameter ini tidak digunakan. Itu membaca lebih mudah dengan garis bawah, terutama jika ada banyak rantai dan Anda dapat segera menyimpulkan jenisnya, seperti yang sering terjadi pada kueri LINQ!
Varvara Kalinina
3
Do(id => Log(id))lebih baik disingkat sebagai Do(Log).
Aluan Haddad