Di C #, saya mulai melihat semua metode ajaib ini muncul, tanpa didukung oleh antarmuka. Mengapa ini dipilih?
Biarkan saya jelaskan.
Sebelumnya di C #, jika suatu objek mengimplementasikan IEnumerable
antarmuka, itu akan secara otomatis menjadi iterable oleh satu foreach
loop. Itu masuk akal bagi saya, karena didukung oleh antarmuka, dan jika saya memiliki Iterator
fungsi saya sendiri di dalam kelas yang diulangi, saya bisa melakukannya tanpa khawatir bahwa itu secara ajaib akan berarti sesuatu yang lain.
Sekarang, tampaknya, (tidak yakin kapan), antarmuka ini tidak lagi diperlukan. Itu hanya perlu memiliki konversi penamaan yang tepat.
Contoh lain adalah membuat objek apa pun ditunggu dengan memiliki metode yang dinamai persis GetAwaiter
yang memiliki beberapa properti tertentu.
Mengapa tidak membuat antarmuka seperti sebelumnya IEnumerable
atau INotifyPropertyChanged
mendukung "sihir" ini secara statis?
Lebih detail tentang apa yang saya maksud di sini:
http://blog.nem.ec/2014/01/01/magic-methods-c-sharp/
Apa pro dan kontra dari metode sulap, dan adakah di mana pun secara online di mana saya dapat menemukan apa pun tentang mengapa keputusan ini dibuat?
async
/await
, maka itu hanya akan bekerja dengan kode yang ditulis setelah .NET 4.5 menjadi cukup luas untuk menjadi target yang layak ... yang pada dasarnya sekarang. Tetapi terjemahan sintaksis murni ke panggilan metode memungkinkan saya untuk menambahkanawait
fungsionalitas ke tipe yang ada setelah fakta.foreach
perulangan di awal. Tidak pernah ada persyaratan untuk objek untuk diterapkanIEnumerable
untukforeach
bekerja. Sudah konvensi untuk melakukannya.Jawaban:
Secara umum "metode ajaib" digunakan ketika itu tidak mungkin untuk membuat antarmuka yang akan bekerja dengan cara yang sama.
Ketika
foreach
pertama kali diperkenalkan di C # 1.0 (perilaku itu tentu tidak baru), ia harus menggunakan metode sihir, karena tidak ada obat generik. Opsi pada dasarnya adalah:Gunakan non-generik
IEnumerable
danIEnumerator
bekerja denganobject
s, yang berarti tipe nilai tinju. Karena iterasi sesuatu seperti daftarint
s harus sangat cepat dan tentunya tidak boleh membuat banyak nilai kotak sampah, ini bukan pilihan yang baik.Tunggu obat generik. Ini mungkin berarti menunda. Net 1.0 (atau setidaknya
foreach
) lebih dari 3 tahun.Gunakan metode ajaib.
Jadi, mereka memilih opsi # 3 dan tetap dengan kami untuk alasan kompatibilitas mundur, meskipun sejak. Net 2.0, membutuhkan
IEnumerable<T>
akan bekerja juga.Penginisialisasi koleksi dapat terlihat berbeda pada setiap jenis koleksi. Bandingkan
List<T>
:dan
Dictionary<TKey, TValue>
:Anda tidak dapat memiliki antarmuka tunggal yang hanya mendukung bentuk pertama
List<T>
dan hanya untuk keduaDictionary<TKey, TValue>
.Metode LINQ biasanya diimplementasikan sebagai metode ekstensi (sehingga hanya ada satu implementasi misalnya LINQ ke Objek untuk semua jenis yang menerapkan
IEnumerable<T>
), yang berarti tidak mungkin menggunakan antarmuka.Untuk
await
,GetResult()
Metode dapat mengembalikan salah satuvoid
atau beberapa jenisT
. Sekali lagi, Anda tidak dapat memiliki antarmuka tunggal yang dapat menangani keduanya. Meskipunawait
sebagian berbasis antarmuka: penunggu harus mengimplementasikanINotifyCompletion
dan juga dapat mengimplementasikanICriticalNotifyCompletion
.sumber
foreach
di C # 1.2 (tidak ada pada MSDN untuk C # 1.0) mengatakan bahwa ekspresi dalamforeach
"Mengevaluasi ke tipe yang mengimplementasikanIEnumerable
atau tipe yang menyatakanGetEnumerator
metode." Dan saya tidak yakin apa yang Anda maksud dengan itu, unboxing di C # selalu eksplisit.foreach(T x in sequence)
menerapkan gips eksplisitT
pada elemen-elemen urutan. Jadi, jika urutannya polosIEnumerable
danT
merupakan tipe nilai, ia akan menghapus kotaknya tanpa ada tulisan eksplisit yang ditulis dalam kode Anda. Salah satu bagian terburuk dari C #.foreach
.)