Apa arti ekspresi lambda _=> expr
?
Apa tujuan _
sebagai masukan bagi lambda?
Contoh:
int count = 0;
list.ForEach(_ => count += 1);
list
adalah IEnumerable<T>
, mereka bisa (dan seharusnya) baru saja menggunakansum = list.Count();
Apa arti ekspresi lambda _=> expr
?
Apa tujuan _
sebagai masukan bagi lambda?
Contoh:
int count = 0;
list.ForEach(_ => count += 1);
list
adalah IEnumerable<T>
, mereka bisa (dan seharusnya) baru saja menggunakansum = list.Count();
Jawaban:
Itu adalah konvensi yang digunakan saat Anda tidak peduli dengan parameternya.
_
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.
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;
Thread t= new Thread(()=>doSomething(x,y)); t.start();
_
adalah nama variabel yang valid. Mereka hanya digunakan _
sebagai variabel.
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
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.
Do(id => Log(id))
lebih baik disingkat sebagai Do(Log)
.