Saya ingin menguraikan poin spesifik yang dibuat Eric Lippert dalam jawabannya dan menyoroti pada kesempatan tertentu yang sama sekali belum disentuh oleh orang lain. Eric berkata:
[...] tugas hampir selalu meninggalkan nilai yang baru saja ditugaskan dalam register.
Saya ingin mengatakan bahwa penugasan akan selalu meninggalkan nilai yang kami coba tetapkan untuk operan kiri kami. Bukan hanya "hampir selalu". Tetapi saya tidak tahu karena saya belum menemukan masalah ini dikomentari dalam dokumentasi. Secara teori mungkin ini merupakan prosedur yang diimplementasikan sangat efektif untuk "meninggalkan" dan tidak mengevaluasi kembali operan kiri, tetapi apakah itu efisien?
'Efisien' ya untuk semua contoh sejauh ini dibangun dalam jawaban utas ini. Tetapi efisien dalam hal properti dan pengindeks yang menggunakan aksesor dan atur? Tidak semuanya. Pertimbangkan kode ini:
class Test
{
public bool MyProperty { get { return true; } set { ; } }
}
Di sini kita memiliki properti, yang bahkan bukan pembungkus untuk variabel pribadi. Setiap kali dipanggil dia akan kembali benar, setiap kali seseorang mencoba untuk menetapkan nilainya dia tidak akan melakukan apa pun. Jadi, setiap kali properti ini dievaluasi, ia harus jujur. Mari lihat apa yang terjadi:
Test test = new Test();
if ((test.MyProperty = false) == true)
Console.WriteLine("Please print this text.");
else
Console.WriteLine("Unexpected!!");
Coba tebak apa yang dicetaknya? Mencetak Unexpected!!
. Ternyata, set accessor memang dipanggil, yang tidak melakukan apa-apa. Namun setelah itu, accessor get tidak pernah dipanggil sama sekali. Tugas hanya meninggalkan false
nilai yang kami coba tetapkan untuk properti kami. Dan false
nilai ini adalah apa yang pernyataan if mengevaluasi.
Saya akan menyelesaikannya dengan contoh dunia nyata yang membuat saya meneliti masalah ini. Saya membuat pengindeks yang merupakan pembungkus yang nyaman untuk koleksi ( List<string>
) yang dimiliki kelas saya sebagai variabel pribadi.
Parameter yang dikirim ke pengindeks adalah string, yang harus diperlakukan sebagai nilai dalam koleksi saya. Pengakses get hanya akan mengembalikan benar atau salah jika nilai itu ada dalam daftar atau tidak. Jadi get accessor adalah cara lain untuk menggunakan List<T>.Contains
metode ini.
Jika set accessor pengindeks dipanggil dengan string sebagai argumen dan operan yang tepat adalah bool true
, ia akan menambahkan parameter itu ke daftar. Tetapi jika parameter yang sama dikirim ke accessor dan operan yang tepat adalah bool false
, ia malah akan menghapus elemen dari daftar. Dengan demikian accessor set digunakan sebagai alternatif yang nyaman untuk keduanya List<T>.Add
dan List<T>.Remove
.
Saya pikir saya punya "API" yang rapi dan kompak yang membungkus daftar dengan logika saya sendiri diimplementasikan sebagai gateway. Dengan bantuan pengindeks saja aku bisa melakukan banyak hal dengan beberapa set penekanan tombol. Misalnya, bagaimana saya bisa mencoba menambahkan nilai ke daftar saya dan memverifikasi bahwa itu ada di sana? Saya pikir ini adalah satu-satunya baris kode yang diperlukan:
if (myObject["stringValue"] = true)
; // Set operation succeeded..!
Tapi seperti contoh saya sebelumnya menunjukkan, dapatkan accessor yang seharusnya melihat apakah nilainya benar-benar ada dalam daftar bahkan tidak dipanggil. The true
nilai selalu tertinggal secara efektif menghancurkan logika apa pun saya telah diimplementasikan dalam mendapatkan accessor saya.