Saya menemukan beberapa kode yang mengatakan
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
Sekarang saya agak akrab dengan ekspresi Lambda. Saya hanya belum melihatnya menggunakannya dengan cara ini.
Apa yang akan menjadi perbedaan antara pernyataan di atas dan
public int MaxHealth = x ? y:z;
Jawaban:
Apa yang Anda lihat adalah anggota bertubuh ekspresi bukan ekspresi lambda.
Ketika kompiler bertemu dengan anggota properti bertubuh ekspresi , pada dasarnya ia mengubahnya menjadi pengambil seperti ini:
(Anda dapat memverifikasi ini sendiri dengan memompa kode ke alat yang disebut TryRoslyn .)
Anggota bertubuh ekspresi - seperti kebanyakan fitur C # 6 - hanyalah gula sintaksis . Ini berarti bahwa mereka tidak menyediakan fungsionalitas yang tidak dapat dicapai melalui fitur yang ada. Sebaliknya, fitur-fitur baru ini memungkinkan sintaksis yang lebih ekspresif dan ringkas untuk digunakan
Seperti yang Anda lihat, anggota yang memiliki ekspresi tubuh memiliki beberapa pintasan yang membuat anggota properti lebih kompak:
return
pernyataan karena kompilator dapat menyimpulkan bahwa Anda ingin mengembalikan hasil ekspresiget
kata kunci karena tersirat oleh penggunaan sintaks anggota bertubuh ekspresi.Saya telah membuat poin terakhir dengan berani karena relevan dengan pertanyaan Anda yang sebenarnya, yang akan saya jawab sekarang.
Perbedaan antara...
Dan...
Apakah sama dengan perbedaan antara ...
Dan...
Yang - jika Anda memahami properti - harus jelas.
Hanya untuk menjadi jelas, daftar pertama adalah properti dengan pengambil di bawah kap yang akan dipanggil setiap kali Anda mengaksesnya. Daftar kedua adalah bidang dengan inisialisasi bidang, yang ekspresinya hanya dievaluasi satu kali, ketika jenisnya dipakai.
Perbedaan dalam sintaksis ini sebenarnya cukup halus dan dapat mengarah pada "gotcha" yang dijelaskan oleh Bill Wagner dalam posting berjudul "AC # 6 gotcha: Inisialisasi vs Anggota Ekspresi yang Bertubuh" .
Sementara anggota yang berekspresi adalah ekspresi seperti lambda , mereka bukan ekspresi lambda. Perbedaan mendasar adalah bahwa ekspresi lambda menghasilkan instance delegasi atau pohon ekspresi. Anggota bertubuh ekspresi hanyalah arahan ke kompiler untuk menghasilkan properti di belakang layar. Kesamaan (lebih atau kurang) dimulai dan diakhiri dengan panah (
=>
).Saya juga akan menambahkan bahwa anggota yang bertubuh ekspresi tidak terbatas pada anggota properti. Mereka mengerjakan semua anggota ini:
Ditambahkan dalam C # 7.0
Namun, mereka tidak bekerja pada anggota ini:
sumber
Ok ... Saya berkomentar bahwa mereka berbeda tetapi tidak bisa menjelaskan dengan pasti bagaimana tetapi sekarang saya tahu.
tidak sama dengan
Inilah bedanya ...
Ketika Anda menggunakan penginisialisasi otomatis, properti menciptakan instance nilai dan menggunakan nilai itu secara terus-menerus. Dalam posting di atas ada tautan yang rusak ke Bill Wagner, yang menjelaskan hal ini dengan baik, dan saya mencari tautan yang benar untuk memahaminya sendiri.
Dalam situasi saya, properti saya otomatis menginisialisasi perintah dalam ViewModel untuk Tampilan. Saya mengubah properti untuk menggunakan initializer bodied ekspresi dan perintah CanExecute berhenti bekerja.
Begini tampilannya dan inilah yang terjadi.
inilah yang saya ubah.
Perbedaannya di sini adalah ketika saya menggunakan
{ get; } =
saya membuat dan referensi perintah SAMA di properti itu. Ketika saya menggunakan,=>
saya benar-benar membuat perintah baru dan mengembalikannya setiap kali properti dipanggil. Oleh karena itu, saya tidak pernah dapat memperbaruiCanExecute
perintah saya karena saya selalu mengatakannya untuk memperbarui referensi baru dari perintah itu.Semua yang dikatakan, jika Anda hanya menunjuk ke bidang dukungan maka itu berfungsi dengan baik. Ini hanya terjadi ketika badan ekspresi atau otomatis membuat nilai kembali.
sumber
Ini adalah fitur baru C # 6 yang disebut anggota bertubuh ekspresi yang memungkinkan Anda untuk mendefinisikan properti pengambil hanya menggunakan fungsi seperti lambda.
Meskipun dianggap sebagai sintaksis gula untuk yang berikut, mereka mungkin tidak menghasilkan IL identik:
Ternyata jika Anda mengkompilasi kedua versi di atas dan membandingkan IL yang dihasilkan untuk masing-masing Anda akan melihat bahwa mereka hampir sama.
Berikut adalah IL untuk versi klasik dalam jawaban ini ketika didefinisikan dalam kelas bernama
TestClass
:Dan di sini adalah IL untuk versi anggota bertubuh ekspresi ketika didefinisikan dalam kelas bernama
TestClass
:Lihat https://msdn.microsoft.com/en-us/magazine/dn802602.aspx untuk informasi lebih lanjut tentang ini dan fitur baru lainnya di C # 6.
Lihat posting ini Perbedaan antara Properti dan Bidang di C # 3.0+ pada perbedaan antara bidang dan pengambil properti di C #.
Memperbarui:
Perhatikan bahwa anggota yang berekspresi diperluas untuk memasukkan properti, konstruktor, finalizer dan pengindeks dalam C # 7.0.
sumber
Ini disebut Expression Bodied Member dan diperkenalkan di C # 6. Ini hanyalah gula sintaksis di atas satu-
get
satunya properti.Itu sama dengan:
Setara dengan deklarasi metode tersedia:
Terutama memungkinkan Anda memendekkan boilerplate.
sumber
Satu hal penting lainnya jika Anda menggunakan C # 6:
'=>' dapat digunakan sebagai ganti 'get' dan hanya untuk metode 'get only' - ini tidak dapat digunakan dengan 'set'.
Untuk C # 7, lihat komentar dari @avenmore di bawah - sekarang dapat digunakan di lebih banyak tempat. Inilah referensi yang bagus - https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/
sumber
Untuk pernyataan berikut dibagikan oleh Alex Booker dalam jawaban mereka
Silakan lihat screenshot berikut , ini menunjukkan bagaimana pernyataan ini (menggunakan tautan SharpLab )
dikonversi ke
Tangkapan layar:
sumber