Bagikan melalui


Gambaran Umum Generik di C++/CLI

Generik adalah jenis parameter yang didukung oleh runtime bahasa umum. Jenis berparameter adalah jenis yang didefinisikan dengan parameter jenis yang tidak diketahui yang ditentukan saat generik digunakan.

Mengapa Generik?

C++ mendukung templat dan templat dan generik mendukung jenis berparameter untuk membuat kelas koleksi yang ditik. Namun, templat menyediakan parameterisasi waktu kompilasi. Anda tidak dapat mereferensikan rakitan yang berisi definisi templat dan membuat spesialisasi baru templat. Setelah dikompilasi, templat khusus terlihat seperti kelas atau metode lainnya. Sebaliknya, generik dipancarkan dalam MSIL sebagai jenis parameter yang dikenal oleh runtime menjadi jenis parameter; kode sumber yang mereferensikan rakitan yang berisi jenis generik dapat membuat spesialisasi jenis generik. Untuk informasi selengkapnya tentang perbandingan templat dan generik C++ standar, lihat Generik dan Templat (C++/CLI).

Fungsi dan Jenis Generik

Jenis kelas, selama mereka adalah jenis terkelola, mungkin umum. Contohnya mungkin kelas List . Jenis objek dalam daftar akan menjadi parameter jenis. Jika Anda memerlukan List kelas untuk berbagai jenis objek, sebelum generik, Anda mungkin telah menggunakan List yang mengambil System::Object sebagai jenis item. Tetapi itu akan memungkinkan objek apa pun (termasuk objek dengan jenis yang salah) untuk digunakan dalam daftar. Daftar seperti itu akan disebut kelas koleksi yang tidak ditiru. Paling baik, Anda dapat memeriksa jenis pada runtime dan melemparkan pengecualian. Atau, Anda mungkin telah menggunakan templat, yang akan kehilangan kualitas generiknya setelah dikompilasi ke dalam rakitan. Konsumen assembly Anda tidak dapat membuat spesialisasi templat mereka sendiri. Generik memungkinkan Anda membuat kelas koleksi yang ditik, katakanlah List<int> (baca sebagai "Daftar int") dan List<double> ("Daftar ganda") yang akan menghasilkan kesalahan waktu kompilasi jika Anda mencoba menempatkan jenis bahwa koleksi tidak dirancang untuk diterima ke dalam koleksi yang ditik. Selain itu, jenis ini tetap umum setelah dikompilasi.

Deskripsi sintaks kelas generik dapat ditemukan di Kelas Generik (C++/CLI). Namespace baru, System.Collections.Generic, memperkenalkan sekumpulan jenis koleksi berparameter termasuk Dictionary<TKey,TValue>, List<T> dan LinkedList<T>.

Fungsi anggota instans dan kelas statis, delegasi, dan fungsi global mungkin juga umum. Fungsi generik mungkin diperlukan jika parameter fungsi memiliki jenis yang tidak diketahui, atau jika fungsi itu sendiri harus bekerja dengan jenis generik. Dalam banyak kasus di mana System::Object mungkin telah digunakan di masa lalu sebagai parameter untuk jenis objek yang tidak diketahui, parameter jenis generik dapat digunakan sebagai gantinya, memungkinkan kode yang lebih aman jenis. Setiap upaya untuk meneruskan jenis yang tidak dirancang fungsi akan ditandai sebagai kesalahan pada waktu kompilasi. Menggunakan System::Object sebagai parameter fungsi, melewati objek yang tidak disengaja yang tidak dimaksudkan untuk ditangani fungsi tidak akan terdeteksi, dan Anda harus melemparkan jenis objek yang tidak diketahui ke jenis tertentu dalam isi fungsi, dan memperhitungkan kemungkinan InvalidCastException. Dengan generik, kode yang mencoba meneruskan objek ke fungsi akan menyebabkan konflik jenis sehingga isi fungsi dijamin memiliki jenis yang benar.

Manfaat yang sama berlaku untuk kelas koleksi yang dibangun di atas generik. Kelas koleksi di masa lalu akan digunakan System::Object untuk menyimpan elemen dalam koleksi. Penyisipan objek jenis yang tidak dirancang untuk koleksi tidak ditandai pada waktu kompilasi, dan seringkali tidak bahkan ketika objek dimasukkan. Biasanya, objek akan dilemparkan ke beberapa jenis lain ketika diakses dalam koleksi. Hanya ketika pemeran gagal, jenis yang tidak terduga akan terdeteksi. Generik memecahkan masalah ini pada waktu kompilasi dengan mendeteksi kode apa pun yang menyisipkan jenis yang tidak cocok (atau secara implisit mengonversi ke) parameter jenis koleksi generik.

Untuk deskripsi sintaks, lihat Fungsi Generik (C++/CLI).

Terminologi Yang Digunakan Dengan Generik

Jenis parameter

Deklarasi generik berisi satu atau beberapa jenis yang tidak diketahui yang dikenal sebagai parameter jenis. Parameter jenis diberi nama yang merupakan singkatan dari jenis dalam isi deklarasi generik. Parameter jenis digunakan sebagai jenis dalam isi deklarasi generik. Deklarasi generik untuk List<T> berisi parameter jenis T.

Ketik Argumen

Argumen jenis adalah jenis aktual yang digunakan sebagai pengganti parameter jenis ketika generik dikhususkan untuk jenis atau jenis tertentu. Misalnya, int adalah argumen jenis dalam List<int>. Jenis nilai dan jenis handel adalah satu-satunya jenis yang diizinkan masuk sebagai argumen jenis generik.

Jenis Yang Dibangun

Jenis yang dibangun dari jenis generik disebut sebagai jenis yang dibangun. Jenis yang tidak sepenuhnya ditentukan, seperti adalah jenis konstruksi terbuka; jenis yang sepenuhnya ditentukan, seperti List<double>, adalah jenis yang dibangun tertutup atau jenis khusus.List<T> Jenis yang dibangun terbuka dapat digunakan dalam definisi jenis atau metode generik lainnya dan mungkin tidak sepenuhnya ditentukan sampai generik penutup ditentukan sendiri. Misalnya, berikut ini adalah penggunaan jenis yang dibangun terbuka sebagai kelas dasar untuk generik:

// generics_overview.cpp
// compile with: /clr /c
generic <typename T>

ref class List {};

generic <typename T>

ref class Queue : public List<T> {};

Batasan

Batasan adalah pembatasan pada jenis yang dapat digunakan sebagai parameter jenis. Misalnya, kelas generik tertentu hanya dapat menerima kelas yang mewarisi dari kelas tertentu, atau menerapkan antarmuka tertentu. Untuk informasi selengkapnya, lihat Batasan pada Parameter Jenis Generik (C++/CLI).

Jenis Referensi dan Jenis Nilai

Jenis handel dan jenis nilai dapat digunakan sebagai argumen jenis. Dalam definisi generik, di mana salah satu jenis dapat digunakan, sintaksnya adalah jenis referensi. Misalnya, -> operator digunakan untuk mengakses anggota jenis parameter jenis apakah jenis yang akhirnya digunakan adalah jenis referensi atau jenis nilai. Saat jenis nilai digunakan sebagai argumen jenis, runtime menghasilkan kode yang menggunakan jenis nilai secara langsung tanpa mengetik jenis nilai.

Saat menggunakan jenis referensi sebagai argumen jenis generik, gunakan sintaks handel. Saat menggunakan jenis nilai sebagai argumen jenis generik, gunakan nama jenis secara langsung.

// generics_overview_2.cpp
// compile with: /clr
generic <typename T>

ref class GenericType {};
ref class ReferenceType {};

value struct ValueType {};

int main() {
    GenericType<ReferenceType^> x;
    GenericType<ValueType> y;
}

Jenis parameter

Parameter jenis dalam kelas generik diperlakukan seperti pengidentifikasi lain. Namun, karena jenisnya tidak diketahui, ada batasan penggunaannya. Misalnya, Anda tidak dapat menggunakan anggota dan metode kelas parameter jenis kecuali parameter jenis diketahui untuk mendukung anggota ini. Artinya, untuk mengakses anggota melalui parameter jenis, Anda harus menambahkan jenis yang berisi anggota ke daftar batasan parameter jenis.

// generics_overview_3.cpp
// compile with: /clr
interface class I {
   void f1();
   void f2();
};

ref struct R : public I {
   virtual void f1() {}
   virtual void f2() {}
   virtual void f3() {}
};

generic <typename T>
where T : I
void f(T t) {
   t->f1();
   t->f2();
   safe_cast<R^>(t)->f3();
}

int main() {
   f(gcnew R());
}

Pembatasan ini juga berlaku untuk operator. Parameter jenis generik yang tidak dibatasi mungkin tidak menggunakan == operator dan != untuk membandingkan dua instans parameter jenis, jika jenisnya tidak mendukung operator ini. Pemeriksaan ini diperlukan untuk generik, tetapi tidak untuk templat, karena generik mungkin dikhususkan pada runtime dengan kelas apa pun yang memenuhi batasan, ketika terlambat untuk memeriksa penggunaan anggota yang tidak valid.

Instans default parameter jenis dapat dibuat dengan menggunakan () operator. Contohnya:

T t = T();

di mana T adalah parameter jenis dalam kelas generik atau definisi metode, menginisialisasi variabel ke nilai defaultnya. Jika T adalah kelas ref, itu akan menjadi penunjuk null; jika T merupakan kelas nilai, objek diinisialisasi ke nol. Ini disebut penginisialisasi default.

Lihat juga

Generik