Saya memiliki fungsi berikut untuk mendapatkan kesalahan validasi kartu. Pertanyaan saya berkaitan dengan berurusan dengan GetErrors. Kedua metode memiliki tipe pengembalian yang sama IEnumerable<ErrorInfo>
.
private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
var errors = GetMoreErrors(card);
foreach (var e in errors)
yield return e;
// further yield returns for more validation errors
}
Apakah mungkin untuk mengembalikan semua kesalahan GetMoreErrors
tanpa harus menyebutkannya?
Kalau dipikir-pikir ini mungkin pertanyaan bodoh, tapi aku ingin memastikan aku tidak salah.
c#
ienumerable
yield
yield-return
John Oxley
sumber
sumber
GetCardProductionValidationErrorsFor
?Jawaban:
Ini jelas bukan pertanyaan bodoh, dan itu adalah sesuatu yang didukung F #
yield!
untuk seluruh koleksi vsyield
untuk satu item. (Itu bisa sangat berguna dalam hal rekursi ekor ...)Sayangnya itu tidak didukung di C #.
Namun, jika Anda memiliki beberapa metode yang masing-masing mengembalikan
IEnumerable<ErrorInfo>
, Anda dapat menggunakanEnumerable.Concat
untuk membuat kode Anda lebih sederhana:Ada satu perbedaan yang sangat penting antara kedua implementasi: yang satu ini akan memanggil semua metode segera , meskipun itu hanya akan menggunakan iterator yang dikembalikan satu per satu. Kode Anda yang ada akan menunggu sampai di-looped melalui semua yang ada di
GetMoreErrors()
dalamnya bahkan sebelum menanyakan tentang kesalahan selanjutnya.Biasanya ini tidak penting, tetapi perlu memahami apa yang akan terjadi ketika.
sumber
GetOtherErrors()
(dll) menunda hasil mereka (karena mereka diimplementasikan menggunakan blok iterator). Coba ubah mereka untuk mengembalikan array baru atau sesuatu seperti itu, dan Anda akan melihat apa yang saya maksud.Anda dapat mengatur semua sumber kesalahan seperti ini (nama metode dipinjam dari jawaban Jon Skeet).
Anda kemudian dapat mengulanginya secara bersamaan.
Atau Anda dapat meratakan sumber kesalahan dengan
SelectMany
.Eksekusi metode di
GetErrorSources
akan ditunda juga.sumber
Saya datang dengan
yield_
cuplikan singkat :Berikut ini cuplikan XML:
sumber
yield!
, seperti di F #.Saya tidak melihat ada yang salah dengan fungsi Anda, saya akan mengatakan itu melakukan apa yang Anda inginkan.
Pikirkan Yield sebagai mengembalikan elemen dalam Enumerasi akhir setiap kali itu dipanggil, jadi ketika Anda memilikinya di loop foreach seperti itu, setiap kali itu dipanggil mengembalikan 1 elemen. Anda memiliki kemampuan untuk menempatkan pernyataan bersyarat di muka Anda untuk memfilter hasil. (hanya dengan tidak menghasilkan kriteria pengecualian Anda)
Jika Anda menambahkan hasil berikutnya nanti dalam metode ini, itu akan terus menambahkan 1 elemen ke enumerasi, sehingga memungkinkan untuk melakukan hal-hal seperti ...
sumber
Saya terkejut tidak ada yang berpikir untuk merekomendasikan metode Ekstensi sederhana
IEnumerable<IEnumerable<T>>
untuk membuat kode ini tetap ditangguhkan pelaksanaannya. Saya penggemar eksekusi yang ditangguhkan karena berbagai alasan, salah satunya adalah jejak memori yang kecil bahkan untuk enumerables yang sangat besar.Dan Anda bisa menggunakannya dalam kasus Anda seperti ini
Demikian pula, Anda dapat menghilangkan fungsi pembungkus
DoGetErrors
dan hanya pindahUnWrap
ke lokasi panggilan.sumber
DoGetErrors(card).SelectMany(x => x)
melakukan hal yang sama dan mempertahankan perilaku yang ditangguhkan. Persis seperti yang disarankan Adam dalam jawabannya .Ya, adalah mungkin untuk mengembalikan semua kesalahan sekaligus. Kembalikan a
List<T>
atauReadOnlyCollection<T>
.Dengan mengembalikan
IEnumerable<T>
Anda mengembalikan urutan sesuatu. Pada permukaan yang mungkin terlihat identik dengan mengembalikan koleksi, tetapi ada sejumlah perbedaan, Anda harus ingat.Koleksi
Urutan
IEnumerable<T>
memungkinkan untuk evaluasi malas, kembaliList<T>
tidak).sumber