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.
Kelas generik merangkum operasi yang tidak spesifik untuk jenis data tertentu. Penggunaan yang paling umum untuk kelas generik adalah dengan koleksi seperti daftar tertaut, tabel hash, tumpukan, antrean, pohon, dan banyak lagi. Operasi seperti menambahkan dan menghapus item dari koleksi dilakukan dengan cara yang sama, terlepas dari jenis data yang disimpan.
Untuk sebagian besar skenario yang memerlukan kelas koleksi, pendekatan yang disarankan adalah menggunakan yang disediakan di pustaka kelas .NET. Untuk informasi selengkapnya tentang menggunakan kelas-kelas ini, lihat Koleksi Generik di .NET.
Biasanya, Anda membuat kelas generik dengan memulai dengan kelas konkret yang ada, dan mengubah jenis menjadi parameter jenis satu per satu hingga mencapai keseimbangan generalisasi dan kegunaan yang optimal. Saat membuat kelas generik Anda sendiri, pertimbangan penting meliputi hal-hal berikut:
Jenis mana yang akan digeneralisasi menjadi parameter jenis.
Sebagai aturan, semakin banyak jenis yang dapat Anda parameterisasi, semakin fleksibel dan dapat digunakan kembali kode Anda. Namun, terlalu banyak generalisasi dapat membuat kode yang sulit dibaca atau dipahami oleh pengembang lain.
Batasan apa, jika ada, untuk diterapkan ke parameter jenis (Lihat Batasan pada Parameter Jenis).
Aturan yang baik adalah menerapkan batasan maksimum yang mungkin masih akan memungkinkan Anda menangani jenis yang harus ditangani. Misalnya, jika tahu bahwa kelas generik Anda dimaksudkan untuk digunakan hanya dengan jenis referensi, terapkan batasan kelas. Pembatasan itu akan mencegah penggunaan tidak sengaja kelas Anda dengan tipe data nilai, dan memungkinkan Anda untuk menggunakan operator
aspadaT, serta memeriksa nilai null.Apakah akan memperhitungkan perilaku generik ke dalam kelas dasar dan subkelas.
Karena kelas generik dapat berfungsi sebagai kelas dasar, pertimbangan desain yang sama berlaku di sini seperti halnya kelas non-generik. Silakan lihat aturan tentang pewarisan dari kelas dasar generik di bagian ini nanti.
Apakah akan mengimplementasikan satu atau beberapa antarmuka generik.
Misalnya, jika merancang kelas yang akan digunakan untuk membuat item dalam koleksi berbasis generik, Anda mungkin harus menerapkan antarmuka seperti IComparable<T> di mana
Tadalah jenis kelas Anda.
Untuk contoh kelas generik sederhana, lihat Pengantar Generik.
Aturan untuk parameter dan batasan jenis memiliki beberapa implikasi untuk perilaku kelas generik, terutama mengenai pewarisan dan aksesibilitas anggota. Sebelum melanjutkan, Anda harus memahami beberapa istilah. Untuk kelas Node<T>generik , kode klien dapat mereferensikan kelas baik dengan menentukan argumen jenis - untuk membuat jenis konstruksi tertutup (Node<int>); atau dengan membiarkan parameter jenis tidak ditentukan - misalnya saat Anda menentukan kelas dasar generik, untuk membuat jenis yang dibangun terbuka (Node<T>). Kelas generik dapat mewarisi dari kelas dasar konkret, yang dibangun tertutup, atau yang dibangun terbuka:
class BaseNode { }
class BaseNodeGeneric<T> { }
// concrete type
class NodeConcrete<T> : BaseNode { }
//closed constructed type
class NodeClosed<T> : BaseNodeGeneric<int> { }
//open constructed type
class NodeOpen<T> : BaseNodeGeneric<T> { }
Kelas bentuk non-generik, dengan kata lain, kelas bentuk konkret dapat mewarisi dari kelas dasar yang dibangun tertutup, tetapi tidak dari kelas dasar yang dibangun terbuka atau dari parameter jenis karena tidak ada cara pada waktu proses bagi kode klien untuk menyediakan argumen jenis yang diperlukan untuk menginstansiasi kelas dasar.
//No error
class Node1 : BaseNodeGeneric<int> { }
//Generates an error
//class Node2 : BaseNodeGeneric<T> {}
//Generates an error
//class Node3 : T {}
Kelas generik yang mewarisi dari jenis yang dibangun terbuka harus menyediakan argumen jenis untuk parameter jenis kelas dasar apa pun yang tidak dibagikan oleh kelas pewarisan, seperti yang ditunjukkan dalam kode berikut:
class BaseNodeMultiple<T, U> { }
//No error
class Node4<T> : BaseNodeMultiple<T, int> { }
//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }
//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {}
Kelas generik yang mewarisi dari jenis yang dibangun terbuka harus menentukan batasan yang merupakan superset, atau menyiratkan, batasan pada jenis dasar:
class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }
Jenis generik dapat menggunakan beberapa parameter dan batasan jenis, sebagai berikut:
class SuperKeyType<K, V, U>
where U : System.IComparable<U>
where V : new()
{ }
Jenis yang dibangun terbuka dan tertutup dapat digunakan sebagai parameter metode:
void Swap<T>(List<T> list1, List<T> list2)
{
//code to swap items
}
void Swap(List<int> list1, List<int> list2)
{
//code to swap items
}
Jika kelas generik mengimplementasikan antarmuka, semua instans kelas tersebut dapat ditransmisikan ke antarmuka tersebut.
Kelas generik bersifat invarian. Dengan kata lain, jika parameter input menentukan List<BaseClass>, Anda akan mendapatkan kesalahan waktu kompilasi jika mencoba memberikan List<DerivedClass>.