Ini berguna saat bekerja dengan COM atau bahasa yang diketik secara dinamis. Sebagai contoh jika Anda akan menggunakan lua atau python untuk scripting bahasa Anda, sangat mudah untuk memanggil kode scripting seolah-olah itu kode biasa.
Kata kunci dinamis baru untuk C # 4.0, dan digunakan untuk memberi tahu kompiler bahwa tipe variabel dapat berubah atau tidak diketahui hingga runtime. Anggap saja mampu berinteraksi dengan Obyek tanpa harus melemparkannya.
dynamic cust =GetCustomer();
cust.FirstName="foo";// works as expected
cust.Process();// works as expected
cust.MissingMethod();// No method found!
Perhatikan bahwa kami tidak perlu memberikan atau mendeklarasikan pelanggan sebagai tipe Pelanggan. Karena kami menyatakannya dinamis, runtime mengambil alih, lalu mencari dan menetapkan properti FirstName untuk kami. Sekarang, tentu saja, ketika Anda menggunakan variabel dinamis, Anda berhenti memeriksa tipe kompiler. Ini berarti panggilan cust.MissingMethod () akan mengkompilasi dan tidak gagal sampai runtime. Hasil dari operasi ini adalah RuntimeBinderException karena MissingMethod tidak didefinisikan pada kelas Pelanggan.
Contoh di atas menunjukkan bagaimana dinamis bekerja saat memanggil metode dan properti. Fitur kuat lainnya (dan berpotensi berbahaya) adalah dapat menggunakan kembali variabel untuk berbagai jenis data. Saya yakin programmer Python, Ruby, dan Perl di luar sana dapat memikirkan sejuta cara untuk mengambil keuntungan dari ini, tapi saya telah menggunakan C # begitu lama sehingga hanya terasa "salah" bagi saya.
dynamic foo =123;
foo ="bar";
OK, jadi Anda kemungkinan besar tidak akan sering menulis kode seperti di atas. Mungkin ada saat-saat ketika penggunaan kembali variabel bisa berguna atau membersihkan sepotong kode warisan. Satu kasus sederhana yang sering saya temui adalah terus-menerus harus memasukkan antara desimal dan ganda.
decimal foo =GetDecimalValue();
foo = foo /2.5;// Does not compile
foo =Math.Sqrt(foo);// Does not compilestring bar = foo.ToString("c");
Baris kedua tidak dikompilasi karena 2,5 diketik sebagai ganda dan baris 3 tidak dikompilasi karena Math.Sqrt mengharapkan ganda. Jelas, yang harus Anda lakukan adalah melemparkan dan / atau mengubah tipe variabel Anda, tetapi mungkin ada situasi di mana dinamika masuk akal untuk digunakan.
dynamic foo =GetDecimalValue();// still returns a decimal
foo = foo /2.5;// The runtime takes care of this for us
foo =Math.Sqrt(foo);// Again, the DLR works its magicstring bar = foo.ToString("c");
Secara pribadi saya tidak suka menggunakan dynamicin c # untuk menyelesaikan masalah yang dapat diselesaikan (mungkin lebih baik) dengan fitur c # standar dan pengetikan statis, atau paling banyak dengan inferensi tipe ( var). dynamicseharusnya hanya digunakan ketika datang ke masalah interoperabilitas dengan DLR. Jika Anda menulis kode dalam bahasa yang diketik statis, seperti c #, maka lakukan, dan jangan meniru bahasa dinamis. Itu jelek.
Philip Daubmeier
40
Jika Anda menggunakan banyak dynamicvariabel dalam kode Anda di mana Anda tidak membutuhkannya (seperti dalam contoh Anda dengan squareroot) Anda menyerah memeriksa kesalahan waktu kompilasi bersih; sebaliknya Anda sekarang mendapatkan kemungkinan kesalahan runtime.
Philip Daubmeier
33
Sebagian besar baik-baik saja, tetapi beberapa kesalahan kecil. Pertama, tidak benar untuk mengatakan bahwa dinamis berarti tipe variabel dapat berubah. Variabel yang dimaksud adalah tipe "dinamis" (dari perspektif bahasa C #; dari perspektif CLR, variabelnya adalah objek tipe). Jenis variabel tidak pernah berubah. Tipe runtime dari nilai suatu variabel dapat berupa tipe apa saja yang kompatibel dengan tipe variabel tersebut. (Atau dalam hal jenis referensi, bisa jadi nol.)
Eric Lippert
15
Mengenai poin kedua Anda: C # sudah memiliki fitur "make variabel Anda dapat memasukkan apa pun ke dalam" - Anda selalu dapat membuat variabel objek tipe. Hal yang menarik tentang dinamika adalah apa yang Anda tunjukkan dalam paragraf pertama Anda: dinamis hampir identik dengan objek, kecuali bahwa analisis semantik ditunda sampai runtime, dan analisis semantik dilakukan pada jenis runtime dari ekspresi. (Sebagian besar. Ada beberapa pengecualian.)
Eric Lippert
18
Saya telah menghabiskan poin downvote pada ini, terutama karena secara implisit menganjurkan penggunaan kata kunci untuk penggunaan umum. Ini memiliki tujuan khusus yang ditargetkan (dijelaskan dengan sempurna dalam jawaban Lasses) dan meskipun jawaban ini -teknis- benar, kemungkinan akan membuat pengembang tersesat.
Eight-Bit Guru
211
Kata dynamickunci ditambahkan, bersama dengan banyak fitur baru lainnya dari C # 4.0, untuk membuatnya lebih mudah untuk berbicara dengan kode yang hidup atau berasal dari runtimes lain, yang memiliki API berbeda.
Ambil sebuah contoh.
Jika Anda memiliki objek COM, seperti Word.Applicationobjek, dan ingin membuka dokumen, metode untuk melakukannya dilengkapi dengan tidak kurang dari 15 parameter, yang sebagian besar bersifat opsional.
Untuk memanggil metode ini, Anda perlu sesuatu seperti ini (saya menyederhanakan, ini bukan kode aktual):
Catat semua argumen itu? Anda harus meneruskannya karena C # sebelum versi 4.0 tidak memiliki gagasan argumen opsional. Di C # 4.0, COM API telah dibuat lebih mudah untuk dikerjakan dengan memperkenalkan:
Lihat seberapa mudah tampilannya, menjadi lebih mudah dibaca?
Mari kita pisahkan itu:
named argument, can skip the rest
|
v
wordApplication.Documents.Open(@"C:\Test.docx",ReadOnly:true);^^||
notice no ref keyword, can pass
actual parameter values instead
Ajaibnya adalah bahwa kompiler C # sekarang akan menyuntikkan kode yang diperlukan, dan bekerja dengan kelas baru di runtime, untuk melakukan hal yang hampir sama persis seperti yang Anda lakukan sebelumnya, tetapi sintaks telah disembunyikan dari Anda, sekarang Anda dapat fokus pada apa , dan tidak begitu banyak tentang bagaimana . Anders Hejlsberg gemar mengatakan bahwa Anda harus memanggil "mantra" yang berbeda, yang merupakan semacam permainan kata-kata pada keajaiban semuanya, di mana Anda biasanya harus melambaikan tangan Anda dan mengucapkan beberapa kata ajaib dalam urutan yang benar. untuk mendapatkan jenis mantra tertentu. Cara API lama untuk berbicara dengan objek COM sangat banyak, Anda perlu melompati banyak rintangan untuk membujuk kompiler untuk mengkompilasi kode untuk Anda.
Hal-hal terurai dalam C # sebelum versi 4.0 bahkan lebih jika Anda mencoba untuk berbicara dengan objek COM yang Anda tidak memiliki antarmuka atau kelas untuk, semua yang Anda miliki adalah IDispatchreferensi.
Jika Anda tidak tahu apa itu, IDispatchpada dasarnya refleksi untuk objek COM. Dengan sebuah IDispatchantarmuka, Anda dapat menanyakan objek "apa nomor id untuk metode yang dikenal sebagai Simpan", dan membangun array dari jenis tertentu yang berisi nilai argumen, dan akhirnya memanggil Invokemetode pada IDispatchantarmuka untuk memanggil metode, melewati semua informasi yang berhasil Anda jelajahi bersama.
Metode Simpan di atas dapat terlihat seperti ini (ini jelas bukan kode yang tepat):
pada dasarnya hanya C # mengejar VB dalam hal ekspresi, tetapi melakukannya dengan cara yang benar, dengan membuatnya dapat diperpanjang, dan tidak hanya untuk COM. Tentu saja ini juga tersedia untuk VB.NET atau bahasa lain yang dibangun di atas runtime .NET.
Anda dapat menemukan informasi lebih lanjut tentang IDispatchantarmuka di Wikipedia: IDispatch jika Anda ingin membaca lebih lanjut tentang itu. Benar-benar hal yang mengerikan.
Namun, bagaimana jika Anda ingin berbicara dengan objek Python? Ada API yang berbeda untuk itu daripada yang digunakan untuk objek COM, dan karena objek Python juga dinamis di alam, Anda perlu menggunakan sihir refleksi untuk menemukan metode yang tepat untuk memanggil, parameternya, dll. Tetapi bukan .NET refleksi, sesuatu yang ditulis untuk Python, sangat mirip dengan kode IDispatch di atas, sama sekali berbeda.
Dan untuk Ruby? API yang berbeda masih.
JavaScript? Kesepakatan yang sama, API yang berbeda untuk itu juga.
Kata kunci dinamis terdiri dari dua hal:
Kata kunci baru dalam C #, dynamic
Seperangkat kelas runtime yang tahu cara menangani berbagai jenis objek, yang mengimplementasikan API spesifik yang dynamicdiperlukan kata kunci, dan memetakan panggilan ke cara yang benar dalam melakukan sesuatu. API bahkan didokumentasikan, jadi jika Anda memiliki objek yang berasal dari runtime yang tidak tercakup, Anda dapat menambahkannya.
Namun, dynamickata kunci tidak dimaksudkan untuk mengganti kode .NET-only yang ada. Tentu, Anda bisa melakukannya, tetapi itu tidak ditambahkan karena alasan itu, dan penulis bahasa pemrograman C # dengan Anders Hejlsberg di depan, sangat bersikeras bahwa mereka masih menganggap C # sebagai bahasa yang diketik dengan kuat, dan tidak akan mengorbankan prinsip itu.
Ini berarti walaupun Anda dapat menulis kode seperti ini:
dynamic x =10;dynamic y =3.14;dynamic z ="test";dynamic k =true;dynamic l = x + y * z - k;
dan mengkompilasinya, itu tidak dimaksudkan sebagai semacam jenis sistem ajaib-mari-cari-cari-apa-yang-Anda-maksud-saat-runtime.
Seluruh tujuannya adalah untuk mempermudah berbicara dengan jenis objek lain.
Ada banyak materi di internet tentang kata kunci, pendukung, lawan, diskusi, kata-kata kasar, pujian, dll.
Saya sarankan Anda mulai dengan tautan berikut dan kemudian google untuk lebih:
Ini juga berguna selain dari COM untuk API JSON web di mana struktur objek JSON yang tidak diserialisasi tidak ditentukan dalam C #. Sebagai contoh , metode Decode System.Web.Helpers.Json mengembalikan objek dinamis .
Dumbledad
Selain tentang "mereka masih menganggap C # sebagai bahasa yang sangat diketik": Eric Lippert bukan penggemar "sangat diketik" sebagai deskripsi.
Andrew Keeton
Saya tidak setuju dengannya, tapi ini masalah pendapat, bukan fakta. "Sangat diketik" bagi saya berarti bahwa kompiler tahu, pada waktu kompilasi, tipe mana yang digunakan, dan dengan demikian menegakkan aturan yang ditetapkan di sekitar tipe tersebut. Fakta bahwa Anda dapat memilih menjadi tipe dinamis yang menunda pemeriksaan aturan dan mengikat ke runtime, bagi saya, tidak berarti bahwa bahasa tersebut diketik dengan lemah. Saya biasanya tidak sangat kontras mengetik untuk mengetik lemah, namun, saya biasanya membandingkannya dengan mengetik secara dinamis, seperti bahasa seperti Python, di mana semuanya adalah bebek sampai menggonggong.
Lasse V. Karlsen
Apa gunanya jawaban ini? Setengahnya adalah tentang parameter opsional dan antarmuka IDispatch.
Xam
Itu sebabnya dynamicditambahkan, untuk mendukung ekosistem lain untuk bagaimana doa metode seperti refleksi dapat dilakukan, serta memberikan semacam pendekatan kotak hitam untuk struktur data dengan cara terdokumentasi untuk mencapai ini.
Lasse V. Karlsen
29
Saya terkejut bahwa tidak ada yang menyebutkan pengiriman ganda . Cara biasa untuk mengatasinya adalah melalui pola Pengunjung dan itu tidak selalu memungkinkan sehingga Anda berakhir dengan iscek bertumpuk .
Jadi, inilah contoh kehidupan nyata dari aplikasi saya sendiri. Alih-alih melakukan:
publicstaticMapDtoBaseCreateDto(ChartItem item){if(item isElevationPoint)returnCreateDtoImpl((ElevationPoint)item);if(item isMapPoint)returnCreateDtoImpl((MapPoint)item);if(item isMapPolyline)returnCreateDtoImpl((MapPolyline)item);//other subtypes followthrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}
Anda melakukannya:
publicstaticMapDtoBaseCreateDto(ChartItem item){returnCreateDtoImpl(item asdynamic);}privatestaticMapDtoBaseCreateDtoImpl(ChartItem item){thrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}privatestaticMapDtoBaseCreateDtoImpl(MapPoint item){returnnewMapPointDto(item);}privatestaticMapDtoBaseCreateDtoImpl(ElevationPoint item){returnnewElevationDto(item);}
Perhatikan bahwa dalam kasus pertama ElevationPointadalah subkelas MapPointdan jika tidak ditempatkan sebelumMapPoint tidak akan pernah tercapai. Ini tidak terjadi dengan dinamis, karena metode pencocokan terdekat akan dipanggil.
Seperti yang mungkin Anda tebak dari kode, fitur itu berguna ketika saya melakukan terjemahan dari objek ChartItem ke versi serializable mereka. Saya tidak ingin mencemari kode saya dengan pengunjung dan saya tidak ingin juga mencemari ChartItemobjek saya dengan atribut spesifik serialisasi yang tidak berguna.
Tidak tahu tentang use case ini. Tapi agak sedikit berantakan. Ini akan membuang penganalisa statis.
Kugel
2
@ Kugel itu benar, tapi saya tidak akan menyebutnya hack . Analisis statis itu baik, tetapi saya tidak akan membiarkannya mencegah saya dari solusi yang elegan, di mana alternatifnya adalah: pelanggaran prinsip terbuka-tertutup (pola Pengunjung) atau meningkatnya kompleksitas siklomatik dengan isditumpuk ditumpuk satu di atas yang lain.
Stelios Adamantidis
4
Nah Anda memiliki opsi pencocokan pola dengan C # 7, bukan?
Kugel
2
Yah adalah operator jauh lebih murah seperti itu (menghindari double cast) dan Anda mendapatkan kembali analisis statis ;-) dan kinerja.
Kugel
@ idbrii tolong jangan ubah jawaban saya. Jangan ragu untuk memberikan komentar dan saya akan mengklarifikasi (jika perlu) karena saya masih aktif di komunitas ini. Juga, tolong jangan gunakan magic; tidak ada yang namanya sihir.
Stelios Adamantidis
11
Itu membuatnya lebih mudah untuk bahasa yang diketik statis (CLR) untuk beroperasi dengan yang dinamis (python, ruby ...) berjalan di DLR (runtime bahasa dinamis), lihat MSDN :
Misalnya, Anda dapat menggunakan kode berikut untuk menambah penghitung dalam XML di C #.
Dan perubahan yang dibutuhkan VM untuk dinamis sebenarnya membuat bahasa dinamis lebih mudah.
Dykam
2
@Dykam: Tidak ada perubahan pada VM. DLR berfungsi dengan baik kembali ke .NET 2.0.
Jörg W Mittag
@ Jorg, ya ada perubahan. DLR sebagian ditulis ulang karena sekarang VM telah membangun dukungan untuk resolusi dinamis.
Dykam
Saya agak terlalu optimis, penelitian menunjukkan perubahan tidak terlalu besar.
Dykam
4
Contoh penggunaan:
Anda mengkonsumsi banyak kelas yang memiliki properti komun 'CreationDate':
publicclassContact{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassCompany{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassOpportunity{// some propertiespublicDateTimeCreationDate{get;set;}}
Jika Anda menulis metode komun yang mengambil nilai properti 'CreationDate', Anda harus menggunakan refleksi:
Jawaban yang sinis tetapi mudah juga benar. Saya telah melihatnya dilakukan hanya untuk menghindari menyatakan struct dengan hasil bahwa kode bekerja jika semuanya baik-baik saja, tetapi pukulan stacknya dengan cara yang tidak terduga segera setelah Anda memindahkan keju itu.
AnthonyVO
Ya, Anda akan melihat bahwa pemotongan sudut klasik dengan banyak fitur bahasa lainnya. Tidak mengherankan bahwa Anda juga akan melihatnya di sini.
Hawkeye4040
1
Ini mengevaluasi saat runtime, sehingga Anda dapat beralih jenis seperti yang Anda bisa dalam JavaScript ke apa pun yang Anda inginkan. Ini legit:
dynamic i =12;
i ="text";
Jadi Anda dapat mengubah jenis yang Anda butuhkan. Gunakan itu sebagai pilihan terakhir; itu bermanfaat, tetapi saya mendengar banyak hal terjadi di bawah layar dalam hal IL yang dihasilkan dan itu bisa datang dengan harga kinerja.
Saya akan ragu untuk mengatakan bahwa itu "sah". Ini pasti akan dikompilasi, jadi itu adalah "kode sah" dalam arti bahwa kompiler sekarang akan mengkompilasinya, dan runtime akan menjalankannya. Tetapi saya tidak akan pernah ingin melihat potongan kode tertentu (atau sesuatu yang mirip dengan itu) di salah satu kode yang saya pertahankan, atau itu akan menjadi pelanggaran yang hampir selalu terjadi.
Lasse V. Karlsen
6
Tentu, tapi itu akan menjadi "sah" dengan "objek" bukannya "dinamis". Anda belum menunjukkan sesuatu yang menarik tentang dinamika di sini.
Eric Lippert
Untuk objek, Anda harus melemparkannya ke jenis yang sesuai, untuk benar-benar memanggil salah satu metodenya ... Anda kehilangan tanda tangan; Anda dapat meminta kode Anda metode apa pun tanpa kompilasi kesalahan, dan itu kesalahan saat runtime. Sedang terburu-buru mengetik, maaf karena tidak menentukan. Dan @Lasse, saya akan setuju dan saya mungkin tidak akan menggunakan banyak dinamis.
Brian Mains
1
Kasus penggunaan resor terakhir tidak dijelaskan
denfromufa
1
Kasus penggunaan terbaik dari variabel tipe 'dinamis' untuk saya adalah ketika, baru-baru ini, saya menulis lapisan akses data di ADO.NET ( menggunakan SQLDataReader ) dan kode itu menggunakan prosedur tersimpan warisan yang sudah ditulis. Ada ratusan prosedur tersimpan warisan yang mengandung sebagian besar logika bisnis. Lapisan akses data saya diperlukan untuk mengembalikan semacam data terstruktur ke lapisan logika bisnis, berbasis C #, untuk melakukan beberapa manipulasi ( walaupun hampir tidak ada ). Setiap prosedur tersimpan mengembalikan set data yang berbeda ( kolom tabel ). Jadi alih-alih membuat lusinan kelas atau struct untuk menyimpan data yang dikembalikan dan meneruskannya ke BLL, saya menulis kode di bawah ini yang terlihat cukup elegan dan rapi.
publicstaticdynamicGetSomeData(ParameterDTO dto){dynamic result =null;stringSPName="a_legacy_stored_procedure";
using (SqlConnection connection =newSqlConnection(DataConnection.ConnectionString)){SqlCommand command =newSqlCommand(SPName, connection);
command.CommandType=System.Data.CommandType.StoredProcedure;
command.Parameters.Add(newSqlParameter("@empid", dto.EmpID));
command.Parameters.Add(newSqlParameter("@deptid", dto.DeptID));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()){while(reader.Read()){dynamic row =newExpandoObject();
row.EmpName= reader["EmpFullName"].ToString();
row.DeptName= reader["DeptName"].ToString();
row.AnotherColumn= reader["AnotherColumn"].ToString();
result = row;}}}return result;}
Anda dapat memanggil ke bahasa dinamis seperti CPython menggunakan pythonnet:
dynamic np = Py.Import("numpy")
Anda dapat menggunakan generik dynamicketika menerapkan operator numerik pada mereka. Ini memberikan keamanan jenis dan menghindari keterbatasan obat generik. Ini pada dasarnya * mengetik bebek:
Kasus penggunaan lain untuk dynamicmengetik adalah untuk metode virtual yang mengalami masalah dengan kovarians atau contravariance. Salah satu contohnya adalah Clonemetode terkenal yang mengembalikan objek dengan tipe yang sama dengan objek yang dipanggil. Masalah ini tidak sepenuhnya diselesaikan dengan pengembalian dinamis karena melewati pemeriksaan tipe statis, tetapi setidaknya Anda tidak perlu menggunakan gips jelek setiap saat seperti saat menggunakan polos object. Kalau tidak dikatakan, para pemain menjadi tersirat.
publicclass A
{// attributes and constructor herepublicvirtualdynamicClone(){var clone =new A();// Do more cloning stuff herereturn clone;}}publicclass B : A
{// more attributes and constructor herepublicoverridedynamicClone(){var clone =new B();// Do more cloning stuff herereturn clone;}}publicclassProgram{publicstaticvoidMain(){
A a =new A().Clone();// No cast needed here
B b =new B().Clone();// and here// do more stuff with a and b}}
Jawaban:
Kata kunci dinamis baru untuk C # 4.0, dan digunakan untuk memberi tahu kompiler bahwa tipe variabel dapat berubah atau tidak diketahui hingga runtime. Anggap saja mampu berinteraksi dengan Obyek tanpa harus melemparkannya.
Perhatikan bahwa kami tidak perlu memberikan atau mendeklarasikan pelanggan sebagai tipe Pelanggan. Karena kami menyatakannya dinamis, runtime mengambil alih, lalu mencari dan menetapkan properti FirstName untuk kami. Sekarang, tentu saja, ketika Anda menggunakan variabel dinamis, Anda berhenti memeriksa tipe kompiler. Ini berarti panggilan cust.MissingMethod () akan mengkompilasi dan tidak gagal sampai runtime. Hasil dari operasi ini adalah RuntimeBinderException karena MissingMethod tidak didefinisikan pada kelas Pelanggan.
Contoh di atas menunjukkan bagaimana dinamis bekerja saat memanggil metode dan properti. Fitur kuat lainnya (dan berpotensi berbahaya) adalah dapat menggunakan kembali variabel untuk berbagai jenis data. Saya yakin programmer Python, Ruby, dan Perl di luar sana dapat memikirkan sejuta cara untuk mengambil keuntungan dari ini, tapi saya telah menggunakan C # begitu lama sehingga hanya terasa "salah" bagi saya.
OK, jadi Anda kemungkinan besar tidak akan sering menulis kode seperti di atas. Mungkin ada saat-saat ketika penggunaan kembali variabel bisa berguna atau membersihkan sepotong kode warisan. Satu kasus sederhana yang sering saya temui adalah terus-menerus harus memasukkan antara desimal dan ganda.
Baris kedua tidak dikompilasi karena 2,5 diketik sebagai ganda dan baris 3 tidak dikompilasi karena Math.Sqrt mengharapkan ganda. Jelas, yang harus Anda lakukan adalah melemparkan dan / atau mengubah tipe variabel Anda, tetapi mungkin ada situasi di mana dinamika masuk akal untuk digunakan.
Baca lebih banyak fitur: http://www.codeproject.com/KB/cs/CSharp4Features.aspx
sumber
dynamic
in c # untuk menyelesaikan masalah yang dapat diselesaikan (mungkin lebih baik) dengan fitur c # standar dan pengetikan statis, atau paling banyak dengan inferensi tipe (var
).dynamic
seharusnya hanya digunakan ketika datang ke masalah interoperabilitas dengan DLR. Jika Anda menulis kode dalam bahasa yang diketik statis, seperti c #, maka lakukan, dan jangan meniru bahasa dinamis. Itu jelek.dynamic
variabel dalam kode Anda di mana Anda tidak membutuhkannya (seperti dalam contoh Anda dengan squareroot) Anda menyerah memeriksa kesalahan waktu kompilasi bersih; sebaliknya Anda sekarang mendapatkan kemungkinan kesalahan runtime.Kata
dynamic
kunci ditambahkan, bersama dengan banyak fitur baru lainnya dari C # 4.0, untuk membuatnya lebih mudah untuk berbicara dengan kode yang hidup atau berasal dari runtimes lain, yang memiliki API berbeda.Ambil sebuah contoh.
Jika Anda memiliki objek COM, seperti
Word.Application
objek, dan ingin membuka dokumen, metode untuk melakukannya dilengkapi dengan tidak kurang dari 15 parameter, yang sebagian besar bersifat opsional.Untuk memanggil metode ini, Anda perlu sesuatu seperti ini (saya menyederhanakan, ini bukan kode aktual):
Catat semua argumen itu? Anda harus meneruskannya karena C # sebelum versi 4.0 tidak memiliki gagasan argumen opsional. Di C # 4.0, COM API telah dibuat lebih mudah untuk dikerjakan dengan memperkenalkan:
ref
opsional untuk API COMSintaks baru untuk panggilan di atas adalah:
Lihat seberapa mudah tampilannya, menjadi lebih mudah dibaca?
Mari kita pisahkan itu:
Ajaibnya adalah bahwa kompiler C # sekarang akan menyuntikkan kode yang diperlukan, dan bekerja dengan kelas baru di runtime, untuk melakukan hal yang hampir sama persis seperti yang Anda lakukan sebelumnya, tetapi sintaks telah disembunyikan dari Anda, sekarang Anda dapat fokus pada apa , dan tidak begitu banyak tentang bagaimana . Anders Hejlsberg gemar mengatakan bahwa Anda harus memanggil "mantra" yang berbeda, yang merupakan semacam permainan kata-kata pada keajaiban semuanya, di mana Anda biasanya harus melambaikan tangan Anda dan mengucapkan beberapa kata ajaib dalam urutan yang benar. untuk mendapatkan jenis mantra tertentu. Cara API lama untuk berbicara dengan objek COM sangat banyak, Anda perlu melompati banyak rintangan untuk membujuk kompiler untuk mengkompilasi kode untuk Anda.
Hal-hal terurai dalam C # sebelum versi 4.0 bahkan lebih jika Anda mencoba untuk berbicara dengan objek COM yang Anda tidak memiliki antarmuka atau kelas untuk, semua yang Anda miliki adalah
IDispatch
referensi.Jika Anda tidak tahu apa itu,
IDispatch
pada dasarnya refleksi untuk objek COM. Dengan sebuahIDispatch
antarmuka, Anda dapat menanyakan objek "apa nomor id untuk metode yang dikenal sebagai Simpan", dan membangun array dari jenis tertentu yang berisi nilai argumen, dan akhirnya memanggilInvoke
metode padaIDispatch
antarmuka untuk memanggil metode, melewati semua informasi yang berhasil Anda jelajahi bersama.Metode Simpan di atas dapat terlihat seperti ini (ini jelas bukan kode yang tepat):
Semua ini hanya untuk membuka dokumen.
VB memiliki argumen opsional dan dukungan untuk sebagian besar dari ini di luar kotak sejak lama, jadi kode C # ini:
pada dasarnya hanya C # mengejar VB dalam hal ekspresi, tetapi melakukannya dengan cara yang benar, dengan membuatnya dapat diperpanjang, dan tidak hanya untuk COM. Tentu saja ini juga tersedia untuk VB.NET atau bahasa lain yang dibangun di atas runtime .NET.
Anda dapat menemukan informasi lebih lanjut tentang
IDispatch
antarmuka di Wikipedia: IDispatch jika Anda ingin membaca lebih lanjut tentang itu. Benar-benar hal yang mengerikan.Namun, bagaimana jika Anda ingin berbicara dengan objek Python? Ada API yang berbeda untuk itu daripada yang digunakan untuk objek COM, dan karena objek Python juga dinamis di alam, Anda perlu menggunakan sihir refleksi untuk menemukan metode yang tepat untuk memanggil, parameternya, dll. Tetapi bukan .NET refleksi, sesuatu yang ditulis untuk Python, sangat mirip dengan kode IDispatch di atas, sama sekali berbeda.
Dan untuk Ruby? API yang berbeda masih.
JavaScript? Kesepakatan yang sama, API yang berbeda untuk itu juga.
Kata kunci dinamis terdiri dari dua hal:
dynamic
dynamic
diperlukan kata kunci, dan memetakan panggilan ke cara yang benar dalam melakukan sesuatu. API bahkan didokumentasikan, jadi jika Anda memiliki objek yang berasal dari runtime yang tidak tercakup, Anda dapat menambahkannya.Namun,
dynamic
kata kunci tidak dimaksudkan untuk mengganti kode .NET-only yang ada. Tentu, Anda bisa melakukannya, tetapi itu tidak ditambahkan karena alasan itu, dan penulis bahasa pemrograman C # dengan Anders Hejlsberg di depan, sangat bersikeras bahwa mereka masih menganggap C # sebagai bahasa yang diketik dengan kuat, dan tidak akan mengorbankan prinsip itu.Ini berarti walaupun Anda dapat menulis kode seperti ini:
dan mengkompilasinya, itu tidak dimaksudkan sebagai semacam jenis sistem ajaib-mari-cari-cari-apa-yang-Anda-maksud-saat-runtime.
Seluruh tujuannya adalah untuk mempermudah berbicara dengan jenis objek lain.
Ada banyak materi di internet tentang kata kunci, pendukung, lawan, diskusi, kata-kata kasar, pujian, dll.
Saya sarankan Anda mulai dengan tautan berikut dan kemudian google untuk lebih:
sumber
dynamic
ditambahkan, untuk mendukung ekosistem lain untuk bagaimana doa metode seperti refleksi dapat dilakukan, serta memberikan semacam pendekatan kotak hitam untuk struktur data dengan cara terdokumentasi untuk mencapai ini.Saya terkejut bahwa tidak ada yang menyebutkan pengiriman ganda . Cara biasa untuk mengatasinya adalah melalui pola Pengunjung dan itu tidak selalu memungkinkan sehingga Anda berakhir dengan
is
cek bertumpuk .Jadi, inilah contoh kehidupan nyata dari aplikasi saya sendiri. Alih-alih melakukan:
Anda melakukannya:
Perhatikan bahwa dalam kasus pertama
ElevationPoint
adalah subkelasMapPoint
dan jika tidak ditempatkan sebelumMapPoint
tidak akan pernah tercapai. Ini tidak terjadi dengan dinamis, karena metode pencocokan terdekat akan dipanggil.Seperti yang mungkin Anda tebak dari kode, fitur itu berguna ketika saya melakukan terjemahan dari objek ChartItem ke versi serializable mereka. Saya tidak ingin mencemari kode saya dengan pengunjung dan saya tidak ingin juga mencemari
ChartItem
objek saya dengan atribut spesifik serialisasi yang tidak berguna.sumber
is
ditumpuk ditumpuk satu di atas yang lain.magic
; tidak ada yang namanya sihir.Itu membuatnya lebih mudah untuk bahasa yang diketik statis (CLR) untuk beroperasi dengan yang dinamis (python, ruby ...) berjalan di DLR (runtime bahasa dinamis), lihat MSDN :
MSDN mencantumkan keuntungan-keuntungan ini:
Lihat MSDN untuk detail lebih lanjut.
sumber
Contoh penggunaan:
Anda mengkonsumsi banyak kelas yang memiliki properti komun 'CreationDate':
Jika Anda menulis metode komun yang mengambil nilai properti 'CreationDate', Anda harus menggunakan refleksi:
Dengan konsep 'dinamis', kode Anda jauh lebih elegan:
sumber
COM interop. Terutama IUnknown. Itu dirancang khusus untuk itu.
sumber
Ini sebagian besar akan digunakan oleh korban RAD dan Python untuk menghancurkan kualitas kode, IntelliSense dan kompilasi deteksi waktu bug.
sumber
Ini mengevaluasi saat runtime, sehingga Anda dapat beralih jenis seperti yang Anda bisa dalam JavaScript ke apa pun yang Anda inginkan. Ini legit:
Jadi Anda dapat mengubah jenis yang Anda butuhkan. Gunakan itu sebagai pilihan terakhir; itu bermanfaat, tetapi saya mendengar banyak hal terjadi di bawah layar dalam hal IL yang dihasilkan dan itu bisa datang dengan harga kinerja.
sumber
Kasus penggunaan terbaik dari variabel tipe 'dinamis' untuk saya adalah ketika, baru-baru ini, saya menulis lapisan akses data di ADO.NET ( menggunakan SQLDataReader ) dan kode itu menggunakan prosedur tersimpan warisan yang sudah ditulis. Ada ratusan prosedur tersimpan warisan yang mengandung sebagian besar logika bisnis. Lapisan akses data saya diperlukan untuk mengembalikan semacam data terstruktur ke lapisan logika bisnis, berbasis C #, untuk melakukan beberapa manipulasi ( walaupun hampir tidak ada ). Setiap prosedur tersimpan mengembalikan set data yang berbeda ( kolom tabel ). Jadi alih-alih membuat lusinan kelas atau struct untuk menyimpan data yang dikembalikan dan meneruskannya ke BLL, saya menulis kode di bawah ini yang terlihat cukup elegan dan rapi.
sumber
dynamic np = Py.Import("numpy")
dynamic
ketika menerapkan operator numerik pada mereka. Ini memberikan keamanan jenis dan menghindari keterbatasan obat generik. Ini pada dasarnya * mengetik bebek:T y = x * (dynamic)x
dimanatypeof(x) is T
sumber
Kasus penggunaan lain untuk
dynamic
mengetik adalah untuk metode virtual yang mengalami masalah dengan kovarians atau contravariance. Salah satu contohnya adalahClone
metode terkenal yang mengembalikan objek dengan tipe yang sama dengan objek yang dipanggil. Masalah ini tidak sepenuhnya diselesaikan dengan pengembalian dinamis karena melewati pemeriksaan tipe statis, tetapi setidaknya Anda tidak perlu menggunakan gips jelek setiap saat seperti saat menggunakan polosobject
. Kalau tidak dikatakan, para pemain menjadi tersirat.sumber