Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Generik memungkinkan Anda menyesuaikan metode, kelas, struktur, atau antarmuka dengan jenis data yang tepat yang ditindaknya. Misalnya, alih-alih menggunakan Hashtable kelas , yang memungkinkan kunci dan nilai dari jenis apa pun, Anda dapat menggunakan Dictionary<TKey,TValue> kelas generik dan menentukan jenis yang diizinkan untuk kunci dan nilai. Di antara manfaat generik adalah peningkatan penggunaan kembali kode dan keamanan jenis.
Menentukan dan menggunakan generik
Generik adalah kelas, struktur, antarmuka, dan metode yang memiliki tempat penampung (parameter jenis) untuk satu atau beberapa jenis yang disimpan atau digunakan. Kelas koleksi generik mungkin menggunakan parameter jenis sebagai tempat penampung untuk jenis objek yang disimpannya. Parameter jenis muncul sebagai jenis bidangnya dan jenis parameter metodenya. Metode generik mungkin menggunakan parameter jenisnya sebagai jenis nilai pengembaliannya atau sebagai jenis salah satu parameter formalnya.
Kode berikut mengilustrasikan definisi kelas generik sederhana.
public class SimpleGenericClass<T>
{
public T Field;
}
Public Class SimpleGenericClass(Of T)
Public Field As T
End Class
Saat Anda membuat instans kelas generik, Anda menentukan jenis aktual untuk menggantikan parameter jenis. Ini menetapkan kelas generik baru, yang disebut sebagai kelas generik terkonstru, dengan jenis yang Anda pilih diganti di semua tempat di mana parameter jenis muncul. Hasilnya adalah kelas jenis aman yang disesuaikan dengan jenis pilihan Anda, seperti yang diilustrasikan kode berikut.
public static void Main()
{
SimpleGenericClass<string> g = new SimpleGenericClass<string>();
g.Field = "A string";
//...
Console.WriteLine($"SimpleGenericClass.Field = \"{g.Field}\"");
Console.WriteLine($"SimpleGenericClass.Field.GetType() = {g.Field.GetType().FullName}");
}
Public Shared Sub Main()
Dim g As New SimpleGenericClass(Of String)
g.Field = "A string"
'...
Console.WriteLine("SimpleGenericClass.Field = ""{0}""", g.Field)
Console.WriteLine("SimpleGenericClass.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub
Terminologi
Istilah berikut digunakan untuk membahas generik di .NET:
Definisi tipe generik adalah deklarasi kelas, struktur, atau antarmuka yang berfungsi sebagai templat, dengan placeholder untuk tipe yang dapat diisi atau digunakan. Misalnya, kelas System.Collections.Generic.Dictionary<TKey,TValue> dapat berisi dua jenis: kunci dan nilai. Karena definisi jenis generik hanyalah templat, Anda tidak dapat membuat instans kelas, struktur, atau antarmuka yang merupakan definisi jenis generik.
Parameter tipe generik, atau parameter tipe, adalah tempat penampung dalam definisi tipe atau metode generik. Jenis System.Collections.Generic.Dictionary<TKey,TValue> generik memiliki dua parameter jenis,
TKeydanTValue, yang mewakili jenis kunci dan nilainya.Jenis generik yang terbangun, atau jenis terbangun, adalah hasil dari menentukan jenis untuk parameter jenis generik dari definisi jenis generik.
Argumen jenis generik adalah jenis apa pun yang digunakan menggantikan parameter jenis generik.
Istilah umum jenis generik mencakup jenis yang dikonstruksi dan definisi jenis generik.
Kovariansi dan kontravariansi parameter jenis generik memungkinkan Anda menggunakan jenis generik yang dibangun yang argumen jenisnya lebih spesifik (kovariansi) atau kurang spesifik (kontravariansi) daripada jenis yang dibangun target. Kovariansi dan kontravariansi secara kolektif disebut sebagai varian. Untuk informasi lebih lanjut, lihat Kovariansi dan kontravariansi.
Batasan adalah limit yang ditempatkan pada parameter jenis generik. Misalnya, Anda dapat membatasi parameter tipe ke jenis-jenis yang mengimplementasikan antarmuka generik System.Collections.Generic.IComparer<T>, untuk memastikan bahwa instans dari tipe tersebut dapat diurutkan. Anda juga dapat membatasi parameter jenis ke jenis yang memiliki kelas dasar tertentu, yang memiliki konstruktor tanpa parameter, atau yang merupakan jenis referensi atau jenis nilai. Pengguna jenis generik tidak dapat menggantikan argumen jenis yang tidak memenuhi batasan.
Definisi metode generik adalah metode dengan dua daftar parameter: daftar parameter tipe generik dan daftar parameter formal. Parameter jenis dapat muncul sebagai jenis pengembalian atau sebagai jenis parameter formal, seperti yang ditunjukkan oleh kode berikut.
T MyGenericMethod<T>(T arg) { T temp = arg; //... return temp; }Function MyGenericMethod(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End FunctionMetode generik dapat muncul pada jenis generik atau nongenerik. Penting untuk dicatat bahwa metode tidak bersifat generik hanya karena termasuk dalam tipe generik, atau bahkan karena memiliki parameter formal yang tipenya adalah parameter generik dari tipe yang melingkupi. Metode hanya umum jika memiliki daftar parameter jenisnya sendiri. Dalam kode berikut, hanya metode
Gyang generik.class A { T G<T>(T arg) { T temp = arg; //... return temp; } } class MyGenericClass<T> { T M(T arg) { T temp = arg; //... return temp; } }Class A Function G(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class Class MyGenericClass(Of T) Function M(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class
Keuntungan dan kekurangan generik
Ada banyak keuntungan menggunakan koleksi dan delegasi generik:
Jenis keamanan. Generik mengalihkan beban jenis keamanan dari Anda ke pengkompilasi. Tidak perlu menulis kode untuk menguji jenis data yang benar karena diberlakukan pada waktu kompilasi. Kebutuhan untuk pengubahan tipe dan kemungkinan terjadi kesalahan pada saat runtime telah berkurang.
Kode yang lebih sedikit dan kode lebih mudah digunakan kembali. Tidak perlu mewarisi dari jenis dasar dan mengambil alih anggota. Misalnya, LinkedList<T> siap digunakan segera. Misalnya, Anda dapat membuat daftar string tertaut dengan deklarasi variabel berikut:
LinkedList<string> llist = new LinkedList<string>();Dim llist As New LinkedList(Of String)()Performa yang lebih baik. Koleksi generik umumnya berkinerja lebih baik untuk menyimpan dan memanipulasi tipe nilai karena tidak perlu mengotakkan tipe nilai.
Delegasi generik memungkinkan panggilan balik jenis aman tanpa perlu membuat beberapa kelas delegasi. Misalnya, deleget umum Predicate<T> memungkinkan Anda membuat metode yang menerapkan kriteria pencarian Anda sendiri untuk tipe tertentu dan menggunakan metode Anda dengan metode dari jenis Array seperti Find, FindLast, dan FindAll.
Generik menyederhanakan kode yang dihasilkan secara dinamis. Saat Anda menggunakan generik dengan kode yang dihasilkan secara dinamis, Anda tidak perlu membuat jenisnya. Ini meningkatkan jumlah skenario di mana Anda dapat menggunakan metode dinamis ringan alih-alih menghasilkan seluruh rakitan. Untuk informasi selengkapnya, lihat Cara: Menentukan dan Menjalankan Metode Dinamis dan DynamicMethod.
Berikut ini adalah beberapa batasan generik:
Jenis generik dapat berasal dari sebagian besar kelas dasar, seperti MarshalByRefObject (dan batasan dapat digunakan untuk mengharuskan parameter jenis generik tersebut berasal dari kelas dasar seperti MarshalByRefObject). Namun, .NET tidak mendukung jenis generik yang terikat konteks. Jenis generik dapat diturunkan dari ContextBoundObject, tetapi mencoba membuat instansi jenis tersebut menyebabkan TypeLoadException.
Enumerasi tidak boleh memiliki parameter jenis generik. Enumerasi hanya dapat generik secara insidental (misalnya, karena ditumpuk dalam jenis generik yang didefinisikan menggunakan Visual Basic, C#, atau C++). Untuk informasi selengkapnya, lihat "Enumerasi" di Sistem Jenis Umum.
Metode dinamis ringan tidak boleh generik.
Di Visual Basic, C#, dan C++, tipe bersarang di dalam tipe generik tidak dapat diinstansiasi kecuali tipe telah dialokasikan ke parameter tipe dari semua tipe pengapit. Cara lain untuk mengatakan ini adalah bahwa dalam refleksi, jenis berlapis yang didefinisikan menggunakan bahasa ini mencakup parameter jenis semua jenis penutupnya. Ini memfasilitasi parameter jenis dari tipe pembungkus untuk digunakan dalam definisi anggota dari tipe bersarang. Untuk informasi selengkapnya, lihat "Tipe Tertanam" di MakeGenericType.
Nota
Jenis berlapis yang didefinisikan dengan memancarkan kode dalam rakitan dinamis atau dengan menggunakan Ilasm.exe (Il Assembler) tidak diperlukan untuk menyertakan parameter jenis dari jenis penutupnya; namun, jika tidak menyertakannya, parameter jenis tidak berada dalam cakupan di kelas berlapis.
Untuk informasi selengkapnya, lihat "Tipe Tertanam" di MakeGenericType.
Pustaka kelas dan dukungan bahasa
.NET menyediakan sejumlah kelas koleksi generik di namespace berikut:
Namespace System.Collections.Generic berisi sebagian besar jenis koleksi generik yang disediakan oleh .NET, seperti List<T> kelas generik dan Dictionary<TKey,TValue> .
Namespace System.Collections.ObjectModel berisi jenis koleksi generik tambahan, seperti ReadOnlyCollection<T> kelas generik, yang berguna untuk mengekspos model objek kepada pengguna kelas Anda.
Antarmuka generik untuk menerapkan perbandingan pengurutan dan kesetaraan disediakan di dalam namespace System, bersama dengan tipe delegasi generik untuk penanganan acara, konversi, dan predikat pencarian.
Namespace System.Numerics menyediakan antarmuka generik untuk fungsionalitas matematika (tersedia di .NET 7 dan versi yang lebih baru). Untuk informasi selengkapnya, lihat Generic math.
Dukungan untuk generik telah ditambahkan ke namespace System.Reflection untuk memeriksa jenis generik dan metode generik, ke System.Reflection.Emit untuk menghasilkan rakitan dinamis yang berisi jenis dan metode generik, dan ke System.CodeDom untuk menghasilkan struktur kode yang menyertakan generik.
Runtime bahasa umum menyediakan opcode dan awalan baru untuk mendukung jenis generik dalam Common Intermediate Language (CIL), termasuk Stelem, Ldelem, Unbox_Any, Constrained, dan Readonly.
Visual C++, C#, dan Visual Basic semuanya memberikan dukungan penuh untuk menentukan dan menggunakan generik. Untuk informasi selengkapnya tentang dukungan bahasa, lihat Jenis Generik di Visual Basic, Pengenalan kepada Generik, dan Gambaran Umum Generik di Visual C++.
Tipe bersarang dan generik
Jenis yang dimasukkan dalam jenis generik dapat bergantung pada parameter tipe dari jenis generik yang melingkupinya. Common Language Runtime menganggap tipe bertingkat sebagai generik, bahkan jika mereka tidak memiliki parameter tipe generik mereka sendiri. Saat Anda membuat instans jenis berlapis, Anda harus menentukan argumen jenis untuk semua jenis generik yang mencakup.
Artikel terkait
| Judul | Deskripsi |
|---|---|
| Koleksi Generik dalam .NET | Menjelaskan kelas koleksi generik dan jenis generik lainnya di .NET. |
| Delegasi Generik untuk Mengelola Array dan List | Menjelaskan peran generik untuk konversi, predikat pencarian, dan tindakan yang harus dilakukan pada elemen dalam array atau koleksi. |
| Matematika generik | Menjelaskan bagaimana Anda dapat melakukan operasi matematika secara generis. |
| Antarmuka Generik | Menjelaskan antarmuka generik yang menyediakan fungsionalitas umum di seluruh keluarga jenis generik. |
| Kovariansi dan Kontravariansi | Menjelaskan kovariansi dan kontravariansi dalam parameter jenis generik. |
| Jenis Koleksi yang Umum Digunakan | Menyediakan informasi ringkasan tentang karakteristik dan skenario penggunaan jenis koleksi di .NET, termasuk jenis generik. |
| Kapan Menggunakan Koleksi Generik | Menjelaskan aturan umum untuk menentukan kapan harus menggunakan jenis koleksi generik. |
| Cara: Menentukan Tipe Generik dengan Reflection Emit | Menjelaskan cara menghasilkan rakitan dinamis yang mencakup jenis dan metode generik. |
| Jenis Generik di Visual Basic | Menjelaskan fitur generik untuk pengguna Visual Basic, termasuk topik cara menggunakan dan menentukan jenis generik. |
| Pengantar Generik | Memberikan gambaran umum tentang menentukan dan menggunakan jenis generik untuk pengguna C#. |
| Gambaran Umum Template di Visual C++ | Menjelaskan fitur generik untuk pengguna C++, termasuk perbedaan antara generik dan templat. |