Pertanyaan Mengapa ekspresi C # lambda tidak bisa terdiri dari pernyataan sederhana jika tanpa memerlukan kawat gigi?


Pertimbangkan ekspresi lambda berikut yang ditetapkan untuk suatu peristiwa.

foo.BarEvent += (s, e) => if (e.Value == true) DoSomething();

Ini tampak cukup lurus ke depan dan hanya terdiri dari satu baris kode. Jadi mengapa saya mendapatkan 2 kesalahan berikut dari debugger?

Istilah ekspresi tidak valid 'jika'


Hanya penugasan, panggilan, kenaikan, pengurangan, menunggu, dan ekspresi objek baru dapat digunakan sebagai pernyataan

Untuk memperbaiki masalah ini, yang harus Anda lakukan hanyalah membungkus Anda if pernyataan dalam tanda kurung.

foo.BarEvent += (s, e) => { if (e.Value == true) DoSomething(); };
//Errors now disappear!

Saya mengerti apa pesan kesalahan ini yang menyatakan. Apa yang saya tidak mengerti adalah mengapa satu kondisi if pernyataan akan menjadi masalah bagi compiler dan mengapa tugas lambda pertama dianggap rusak.

Bisakah seseorang menjelaskan masalahnya?


21
2017-08-15 13:31


asal


Jawaban:


Tanpa { } Anda menyatakan tubuh ekspresi, dengan { } ini adalah badan pernyataan. Lihat Lambda Expressions (Panduan Pemrograman C #):

  • Sebuah ekspresi lambda mengembalikan hasil ekspresi

  • SEBUAH pernyataan lambda menyerupai ekspresi lambda kecuali bahwa pernyataan (s) tertutup dalam kurung [...] Tubuh lambda pernyataan dapat terdiri dari sejumlah pernyataan.

Jadi, jika Anda menginginkan pernyataan dan bukan ekspresi, gunakan tanda kurung.


37
2017-08-15 13:34



Lihat Lambda Expressions.

Ada dua jenis lambdas, Expression Lambdas (no {}) dan Pernyataan Lambdas (dengan {}).

Perbedaan utama di antara mereka adalah bahwa Ekspresi Lambdas didefinisikan untuk mengembalikan nilai dihitung oleh sisi kanan mereka. Tapi if() adalah pernyataan, bukan ekspresi. Tidak ada nilai yang terkait dengan if. Anda akan melihat bahwa semua elemen bahasa "diizinkan" dalam pesan kesalahan yang Anda berikan adalah ekspresi: mereka menghitung a nilai.


9
2017-08-15 13:39



Seperti yang saya pahami, tidak akan menjadi masalah untuk menerapkan ini. Tim C # telah menerapkan cara fungsionalitas yang lebih menakutkan (misalnya LINQ)

Tetapi masalahnya adalah di mana Anda menarik garis?

jika

b => if (b) DoSomething()` 

diizinkan, lalu, mengapa tidak

b => if (b) {DoSomething1(); DoSomething2();}

diperkenankan. Atau

list => foreach (var item in list) DoSomething(item)

dll, dll, dll ... Dan sebelum Anda menyadarinya, Anda memiliki seluruh tim yang mendukung fitur yang pada dasarnya sepele.

Satu-satunya cara yang pasti untuk tidak memiliki bug dalam suatu fitur adalah dengan tidak mengimplementasikan fitur.

Implementasi saat ini adalah yang paling optimal, karena ia berfungsi di sebagian besar kasus, dan tidak terlalu rumit di bagian lainnya (sebuah {} sederhana tidak terlalu mudah terbebani, sementara membuatnya lebih mudah untuk compiler).


0
2017-08-15 13:41



Lihatlah ini dengan cara ini. Anda memiliki pernyataan bersyarat yang mengaktifkan satu baris jika benar.

if (stuff) do stuff;

Yang juga bisa ditulis

if (stuff)
     do stuff;

Karena Anda hanya memanggil satu baris kode, Anda tidak perlu dua tanda kurung. Jika lebih, maka Anda harus menggunakan tanda kurung.

if (stuff)
{
     do stuff;
     do more stuff;
}

Kemudian Anda menggabungkannya dengan metode anonim, yang berperilaku dengan cara yang sama

() => do stuff;

Lebih dari satu pernyataan, menggunakan tanda kurung seperti kondisional.

() => {do stuff; do more stuff;}

Tapi sekarang Anda menumpuknya, tetapi masih berharap dapat menggunakan jalan pintas. Yang benar-benar apa itu, jalan pintas yang menyiratkan tanda kurung untuk satu pernyataan tunggal.

Jadi Anda bersarang satu jalan pintas di dalam pintasan lain. C # hanya memaksa Anda untuk secara eksplisit menguraikan cara pintas bersarang.


-1
2017-08-15 13:41