Setelah hampir 4 tahun pengalaman, saya belum melihat kode di mana kata kunci hasil digunakan. Adakah yang bisa menunjukkan kepada saya penggunaan praktis (bersama penjelasan) dari kata kunci ini, dan jika demikian, bukankah ada cara lain yang lebih mudah untuk memenuhi apa yang dapat dilakukannya?
76
yield
dapat digunakan untuk secara umum.Jawaban:
Efisiensi
Kata
yield
kunci tersebut secara efektif menciptakan penghitungan malas atas item koleksi yang bisa jauh lebih efisien. Misalnya, jikaforeach
perulangan Anda hanya mengulangi 5 item pertama dari 1 juta item, maka itu semuayield
pengembalian, dan Anda tidak membangun koleksi 1 juta item secara internal terlebih dahulu. Anda juga ingin menggunakanyield
denganIEnumerable<T>
nilai pengembalian dalam skenario pemrograman Anda sendiri untuk mencapai efisiensi yang sama.Contoh efisiensi yang diperoleh dalam skenario tertentu
Bukan metode iterator, potensi penggunaan koleksi besar yang tidak efisien,
(Koleksi perantara dibangun memiliki banyak item)
Versi Iterator, efisien
(Tidak ada koleksi perantara dibangun)
Sederhanakan beberapa skenario pemrograman
Dalam kasus lain, ini membuat beberapa jenis penyortiran dan penggabungan daftar lebih mudah diprogram karena Anda hanya
yield
memasukkan kembali item dalam urutan yang diinginkan daripada menyortirnya menjadi koleksi perantara dan menukarnya di sana. Ada banyak skenario seperti itu.Hanya satu contoh adalah penggabungan dua daftar:
Metode ini menghasilkan kembali satu daftar item yang berdekatan, secara efektif penggabungan tanpa koleksi perantara yang diperlukan.
Info lebih lanjut
The
yield
kata kunci hanya dapat digunakan dalam konteks metode iterator (memiliki jenis kembalinyaIEnumerable
,IEnumerator
,IEnumerable<T>
atauIEnumerator<T>
.) Dan ada hubungan khusus denganforeach
. Iterator adalah metode khusus. The MSDN dokumentasi hasil dan iterator dokumentasi berisi banyak informasi menarik dan penjelasan tentang konsep-konsep. Pastikan untuk berkorelasi dengan paraforeach
kata kunci dengan membaca tentang hal itu juga, untuk melengkapi pemahaman Anda tentang iterator.Untuk mempelajari tentang bagaimana iterator mencapai efisiensinya, rahasianya ada pada kode IL yang dihasilkan oleh kompiler C #. IL yang dihasilkan untuk metode iterator berbeda secara drastis dari yang dihasilkan untuk metode reguler (non-iterator). Artikel ini (Apa Kata Kunci Hasil Penghasilan yang Sebenarnya?) Memberikan wawasan semacam itu.
sumber
database.Customers.Count()
penghitungan seluruh pelanggan melakukan pencacahan, sehingga membutuhkan kode yang lebih efisien untuk melewati setiap item?Beberapa waktu yang lalu saya memiliki contoh praktis, mari kita asumsikan Anda memiliki situasi seperti ini:
Objek tombol tidak tahu posisinya sendiri dalam koleksi. Batasan yang sama berlaku untuk
Dictionary<T>
atau jenis koleksi lainnya.Ini solusi saya menggunakan
yield
kata kunci:Dan itulah cara saya menggunakannya:
Saya tidak perlu membuat
for
lingkaran di koleksi saya untuk menemukan indeks. Tombol saya memiliki ID dan ini juga digunakan sebagai indeksIndexerList<T>
, jadi Anda menghindari ID atau indeks yang berlebihan - itulah yang saya suka! Indeks / Id dapat berupa angka arbitrer.sumber
Contoh praktis dapat ditemukan di sini:
http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html
Ada beberapa keuntungan menggunakan hasil di atas kode standar:
Namun, seperti yang dikatakan Jan_V (hanya mengalahkan saya dengan beberapa detik :-) Anda dapat hidup tanpanya karena secara internal kompiler akan menghasilkan kode yang hampir identik dalam kedua kasus.
sumber
Ini sebuah contoh:
https://bitbucket.org/ant512/workingweek/src/a745d02ba16f/source/WorkingWeek/Week.cs#cl-158
Kelas melakukan perhitungan tanggal berdasarkan minggu kerja. Saya dapat memberi contoh pada kelas bahwa Bob bekerja pada pukul 9:30 hingga 17:30 setiap hari setiap hari dengan istirahat satu jam untuk makan siang pada pukul 12:30. Dengan pengetahuan ini, fungsi AscendingShifts () akan menghasilkan objek shift kerja antara tanggal yang disediakan. Untuk daftar semua shift kerja Bob antara 1 Jan dan 1 Februari tahun ini, Anda akan menggunakannya seperti ini:
Kelas tidak benar-benar beralih pada koleksi. Namun, pergeseran antara dua tanggal dapat dianggap sebagai koleksi. The
yield
Operator memungkinkan untuk iterate atas koleksi membayangkan ini tanpa menciptakan koleksi sendiri.sumber
Saya memiliki lapisan data db kecil yang memiliki
command
kelas di mana Anda mengatur teks perintah SQL, jenis perintah, dan mengembalikan IEnumerable dari 'parameter perintah'.Pada dasarnya idenya adalah mengetik perintah CLR alih-alih mengisi
SqlCommand
properti dan parameter secara manual sepanjang waktu.Jadi ada fungsi yang terlihat seperti ini:
Kelas yang mewarisi
command
kelas ini memiliki propertiAge
danName
.Kemudian Anda bisa membuat
command
objek baru mengisi propertinya dan mengirimkannya kedb
antarmuka yang benar-benar melakukan panggilan perintah.Semua dalam semua membuatnya sangat mudah untuk bekerja dengan perintah SQL dan tetap mengetiknya.
sumber
Meskipun kasus penggabungan telah dicakup dalam jawaban yang diterima, izinkan saya menunjukkan kepada Anda metode ekstensi params hasil-gabung ™:
Saya menggunakan ini untuk membangun paket-paket protokol jaringan:
The
MarkChecksum
metode, misalnya, terlihat seperti ini. Dan adayield
juga:Tapi hati-hati ketika menggunakan metode agregat seperti Sum () dalam metode enumerasi karena mereka memicu proses enumerasi terpisah.
sumber
Pencarian Elastis .NET contoh repo memiliki contoh yang bagus untuk menggunakan
yield return
untuk mempartisi koleksi menjadi beberapa koleksi dengan ukuran tertentu:https://github.com/elastic/elasticsearch-net-example/blob/master/src/NuSearch.Domain/Extensions/PartitionExtension.cs
sumber
Memperluas jawaban Jan_V, saya baru saja menemukan kasus dunia nyata yang terkait dengan itu:
Saya perlu menggunakan versi Kernel32 dari FindFirstFile / FindNextFile. Anda mendapatkan pegangan dari panggilan pertama dan mengumpankannya ke semua panggilan berikutnya. Bungkus ini dalam enumerator dan Anda mendapatkan sesuatu yang bisa langsung Anda gunakan dengan foreach.
sumber