Metode ekstensi dan objek dinamis

96

Saya akan meringkas masalah saya ke dalam potongan kode berikut.

List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());

Kode di atas berfungsi dengan baik.

Sekarang saya mencoba yang berikut ini

dynamic dList = list;
 Console.WriteLine(dList.First());

tapi saya mendapatkan RuntimeBinderException. Mengapa demikian?

santosh singh
sumber
Ini sepertinya duplikat dari pertanyaan ini yang ditanyakan hanya 4 hari yang lalu stackoverflow.com/questions/5270782/…
jbtule
@jbtule Perbedaannya adalah thisdinamis di sini, tetapi jika Anda mendarat di sini, Anda mungkin harus melihat pertanyaan itu juga
nik.shornikov

Jawaban:

131

Untuk memperluas jawaban Stecya ... metode ekstensi tidak didukung oleh pengetikan dinamis dalam bentuk metode ekstensi , yaitu disebut seolah-olah metode instan. Namun, ini akan berhasil:

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));

Tentu saja, itu mungkin berguna atau tidak. Jika Anda dapat memberikan lebih banyak informasi tentang mengapa dan bagaimana Anda mencoba menggunakan pengetikan dinamis, kami mungkin dapat membantu lebih banyak.

Jon Skeet
sumber
Saya bermain dengan objek dinamis dan mendapat pengecualian ini Apakah Anda pernah menulis artikel tentang topik ini, di mana menggunakan atau tidak objek dinamis
santosh singh
19
@ Geek: Secara pribadi aturan praktis saya hanya digunakan di dynamictempat yang benar-benar diperlukan ... pada dasarnya jika Anda mengakses anggota dengan refleksi, itu pertanda besar. Di sisi lain, saya adalah seorang typer statis yang keras - orang lain mungkin menyarankan kebijakan yang kurang pesimis :)
Jon Skeet
2
Mungkin lebih mudah dibaca untuk mentransmisikan kembali ke tipe tahu, ini berfungsi: Console.WriteLine (((List <int>) dList) .First ()); Atau Console.WriteLine ((dList as List <int>) .First ()) ;.
AVee
138

Untuk memperluas jawaban Jon, alasan ini tidak berhasil adalah karena dalam metode ekstensi kode non-dinamis biasa bekerja dengan melakukan pencarian penuh dari semua kelas yang diketahui oleh kompilator untuk kelas statis yang memiliki metode ekstensi yang cocok. Pencarian berjalan secara berurutan berdasarkan namespace bersarang dan usingarahan yang tersedia di setiap namespace.

Itu berarti bahwa untuk mendapatkan pemanggilan metode ekstensi dinamis diselesaikan dengan benar, DLR harus tahu pada waktu proses apa semua namespace nestings dan usingarahan berada di kode sumber Anda . Kami tidak memiliki mekanisme yang berguna untuk menyandikan semua informasi itu ke dalam situs panggilan. Kami mempertimbangkan untuk menciptakan mekanisme seperti itu, tetapi memutuskan bahwa biayanya terlalu tinggi dan menghasilkan terlalu banyak risiko jadwal sehingga tidak layak dilakukan.

Eric Lippert
sumber
Terima kasih banyak atas penjelasannya.
santosh singh
3
Apakah fitur seperti itu sebentar lagi? Ini pasti akan menjadi perubahan yang menghancurkan; panggilan yang saat ini memunculkan RunTimeBinderExceptions tiba-tiba akan mulai bekerja saat mengompilasi ulang sumber. Selain itu, apakah ada risiko keamanan yang terkait dengan penerapan fitur semacam itu?
Ani
5
@ani: Apakah kami berencana menerapkan fitur itu? Tidak. Apakah ada resiko keamanan? Saya tidak mengetahui apapun; jenis risiko keamanan yang Anda pikirkan? Mulailah dengan mengatakan siapa penyerang dan ancaman apa yang mereka buat terhadap pengguna.
Eric Lippert
@EricLippert, saya telah memahami bahwa semua dynamicobjek sama dengan C # :, DynamicObjectjadi tidak ada cara untuk membedakannya dan merupakan salah satu alasan mengapa tidak mungkin menambahkan metode ekstensi dynamic, bukan?
Tom Sarduy
@EricLippert pertimbangkan untuk memperluas jawaban ini sedikit lagi dan menambahkan kalimat di sepanjang baris "Ketika salah satu parameternya dinamis, maka semua resolusi ditangguhkan hingga waktu proses". Meskipun jelas bagi Anda, bit penting ini sulit ditemukan di tempat lain di SO (lihat stackoverflow.com/questions/48324768 misalnya)
Alexei Levenkov
18

Karena First()bukan metode List. Ini didefinisikan dalam Linq Extension keIEnumerable<>

Stecya
sumber