Untuk apa tipe 'dinamis' dalam C # 4.0 digunakan?


236

C # 4.0 memperkenalkan tipe baru yang disebut 'dinamis'. Kedengarannya bagus, tapi untuk apa programmer menggunakannya?

Apakah ada situasi di mana itu bisa menyelamatkan hari?



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.
CodesInChaos


Saya harap artikel ini memiliki jawaban lengkap untuk pertanyaan Anda visualstudiomagazine.com/Articles/2011/02/01/...
Pengembang

Jawaban:


196

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 compile
string 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 magic
string bar = foo.ToString("c");

Baca lebih banyak fitur: http://www.codeproject.com/KB/cs/CSharp4Features.aspx


97
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):

object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing);

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:

  1. Argumen opsional
  2. Membuat refopsional untuk API COM
  3. Argumen yang dinamai

Sintaks baru untuk panggilan di atas adalah:

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

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):

string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);

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:

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

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:

  1. Kata kunci baru dalam C #, dynamic
  2. 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:


12
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:

public static MapDtoBase CreateDto(ChartItem item)
{
    if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
    if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
    if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
    //other subtypes follow
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

Anda melakukannya:

public static MapDtoBase CreateDto(ChartItem item)
{
    return CreateDtoImpl(item as dynamic);
}

private static MapDtoBase CreateDtoImpl(ChartItem item)
{
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

private static MapDtoBase CreateDtoImpl(MapPoint item)
{
    return new MapPointDto(item);
}

private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
    return new ElevationDto(item);
}

Perhatikan bahwa dalam kasus pertama ElevationPointadalah subkelas MapPointdan jika tidak ditempatkan sebelum MapPoint 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 #.

Scriptobj.SetProperty("Count", ((int)GetProperty("Count")) + 1);

Dengan menggunakan DLR, Anda bisa menggunakan kode berikut sebagai ganti untuk operasi yang sama.

scriptobj.Count += 1;

MSDN mencantumkan keuntungan-keuntungan ini:

  • Menyederhanakan Porting Bahasa Dinamis ke .NET Framework
  • Mengaktifkan Fitur Dinamis dalam Bahasa yang Diketik Secara Statis
  • Memberikan Manfaat DLR dan .NET Framework di Masa Depan
  • Memungkinkan Berbagi Perpustakaan dan Objek
  • Menyediakan Pengiriman dan Doa Dinamis Cepat

Lihat MSDN untuk detail lebih lanjut.


1
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':

public class Contact
{
    // some properties

    public DateTime CreationDate { get; set; }        
}

public class Company
{
    // some properties

    public DateTime CreationDate { get; set; }

}

public class Opportunity
{
    // some properties

    public DateTime CreationDate { get; set; }

}

Jika Anda menulis metode komun yang mengambil nilai properti 'CreationDate', Anda harus menggunakan refleksi:

    static DateTime RetrieveValueOfCreationDate(Object item)
    {
        return (DateTime)item.GetType().GetProperty("CreationDate").GetValue(item);
    }

Dengan konsep 'dinamis', kode Anda jauh lebih elegan:

    static DateTime RetrieveValueOfCreationDate(dynamic item)
    {
        return item.CreationDate;
    }

7
Mengetik bebek, bagus. Namun Anda harus menggunakan antarmuka untuk ini jika itu adalah tipe Anda.
Kugel

3

COM interop. Terutama IUnknown. Itu dirancang khusus untuk itu.


2

Ini sebagian besar akan digunakan oleh korban RAD dan Python untuk menghancurkan kualitas kode, IntelliSense dan kompilasi deteksi waktu bug.


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.


7
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.

public static dynamic GetSomeData(ParameterDTO dto)
        {
            dynamic result = null;
            string SPName = "a_legacy_stored_procedure";
            using (SqlConnection connection = new SqlConnection(DataConnection.ConnectionString))
            {
                SqlCommand command = new SqlCommand(SPName, connection);
                command.CommandType = System.Data.CommandType.StoredProcedure;                
                command.Parameters.Add(new SqlParameter("@empid", dto.EmpID));
                command.Parameters.Add(new SqlParameter("@deptid", dto.DeptID));
                connection.Open();
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        dynamic row = new ExpandoObject();
                        row.EmpName = reader["EmpFullName"].ToString();
                        row.DeptName = reader["DeptName"].ToString();
                        row.AnotherColumn = reader["AnotherColumn"].ToString();                        
                        result = row;
                    }
                }
            }
            return result;
        }

0
  1. Anda dapat memanggil ke bahasa dinamis seperti CPython menggunakan pythonnet:

dynamic np = Py.Import("numpy")

  1. Anda dapat menggunakan generik dynamicketika menerapkan operator numerik pada mereka. Ini memberikan keamanan jenis dan menghindari keterbatasan obat generik. Ini pada dasarnya * mengetik bebek:

T y = x * (dynamic)xdimana typeof(x) is T


0

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.

public class A
{
    // attributes and constructor here
    public virtual dynamic Clone()
    {
        var clone = new A();
        // Do more cloning stuff here
        return clone;
    }
}

public class B : A
{
    // more attributes and constructor here
    public override dynamic Clone()
    {
        var clone = new B();    
        // Do more cloning stuff here
        return clone;
    }
}    

public class Program
{
    public static void Main()
    {
        A a = new A().Clone();  // No cast needed here
        B b = new B().Clone();  // and here
        // do more stuff with a and b
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.