Bagikan melalui


Batasan pada parameter jenis generik (C++/CLI)

Dalam deklarasi jenis atau metode generik, Anda dapat memenuhi syarat parameter jenis dengan batasan. Batasan adalah persyaratan bahwa jenis yang digunakan sebagai argumen jenis harus dipenuhi. Misalnya, batasan mungkin argumen jenis harus mengimplementasikan antarmuka tertentu atau mewarisi dari kelas tertentu.

Batasan bersifat opsional; tidak menentukan batasan pada parameter setara dengan menggunakan Object batasan.

Sintaks

where type-parameter : constraint-list

Parameter

type-parameter
Salah satu pengidentifikasi parameter jenis untuk dibatasi.

constraint-list
Daftar spesifikasi batasan yang dipisahkan koma. Daftar ini dapat mencakup antarmuka yang akan diimplementasikan oleh type-parameter.

Daftar juga dapat menyertakan kelas. Untuk memenuhi batasan kelas dasar, argumen jenis harus kelas yang sama dengan batasan atau berasal dari batasan. Tentukan ref class untuk menunjukkan argumen jenis harus merupakan jenis referensi, termasuk jenis , , interfacedelegate, atau array apa punclass. Tentukan value class untuk menunjukkan argumen jenis harus merupakan tipe nilai. Jenis nilai apa pun kecuali Nullable<T> dapat ditentukan.

Anda juga dapat menentukan gcnew() untuk menunjukkan argumen jenis harus memiliki konstruktor tanpa parameter publik.

Anda juga dapat menentukan parameter generik sebagai batasan. Argumen jenis yang disediakan untuk jenis yang Anda batasi harus atau berasal dari jenis batasan. Parameter ini disebut batasan jenis telanjang.

Keterangan

Klausa batasan where terdiri dari diikuti oleh parameter jenis, titik dua (:), dan batasan, yang menentukan sifat pembatasan pada parameter jenis. where adalah kata kunci yang sensitif terhadap konteks. Untuk informasi selengkapnya, lihat Kata kunci peka konteks. Pisahkan beberapa where klausa dengan spasi.

Batasan diterapkan ke parameter jenis untuk menempatkan batasan pada jenis yang dapat digunakan sebagai argumen untuk jenis atau metode generik.

Batasan kelas dan antarmuka menentukan bahwa jenis argumen harus atau mewarisi dari kelas tertentu atau mengimplementasikan antarmuka tertentu.

Penerapan batasan pada jenis atau metode generik memungkinkan kode dalam jenis atau metode tersebut untuk memanfaatkan fitur yang diketahui dari jenis yang dibatasi. Misalnya, Anda dapat mendeklarasikan kelas generik sehingga parameter jenis mengimplementasikan IComparable<T> antarmuka:

// generics_constraints_1.cpp
// compile with: /c /clr
using namespace System;
generic <typename T>
where T : IComparable<T>
ref class List {};

Batasan ini mengharuskan argumen jenis yang digunakan untuk T diterapkan IComparable<T> pada waktu kompilasi. Ini juga memungkinkan metode antarmuka, seperti CompareTo, untuk dipanggil. Tidak ada cast yang diperlukan pada instans parameter jenis untuk memanggil metode antarmuka.

Metode statis dalam kelas argumen jenis tidak dapat dipanggil melalui parameter jenis; mereka hanya dapat dipanggil melalui jenis bernama aktual.

Batasan tidak boleh berupa jenis nilai, termasuk jenis bawaan seperti int atau double. Karena jenis nilai tidak dapat memiliki kelas turunan, hanya satu kelas yang dapat memenuhi batasan. Dalam hal ini, generik dapat ditulis ulang dengan parameter jenis digantikan oleh jenis nilai tertentu.

Batasan diperlukan dalam beberapa kasus karena pengkompilasi tidak akan mengizinkan penggunaan metode atau fitur lain dari jenis yang tidak diketahui kecuali batasan menyiratkan bahwa jenis yang tidak diketahui mendukung metode atau antarmuka.

Beberapa batasan untuk parameter jenis yang sama dapat ditentukan dalam daftar yang dipisahkan koma

// generics_constraints_2.cpp
// compile with: /c /clr
using namespace System;
using namespace System::Collections::Generic;
generic <typename T>
where T : List<T>, IComparable<T>
ref class List {};

Dengan beberapa parameter jenis, gunakan salah satu klausa di mana untuk setiap parameter jenis. Contohnya:

// generics_constraints_3.cpp
// compile with: /c /clr
using namespace System;
using namespace System::Collections::Generic;

generic <typename K, typename V>
   where K: IComparable<K>
   where V: IComparable<K>
ref class Dictionary {};

Gunakan batasan dalam kode Anda sesuai dengan aturan berikut:

  • Jika beberapa batasan tercantum, batasan dapat dicantumkan dalam urutan apa pun.

  • Batasan juga dapat berupa jenis kelas, seperti kelas dasar abstrak. Namun, batasan tidak boleh berupa jenis nilai atau sealed kelas.

  • Batasan tidak dapat berupa parameter jenis, tetapi dapat melibatkan parameter jenis dalam jenis yang dibangun secara terbuka. Contohnya:

    // generics_constraints_4.cpp
    // compile with: /c /clr
    generic <typename T>
    ref class G1 {};
    
    generic <typename Type1, typename Type2>
    where Type1 : G1<Type2>   // OK, G1 takes one type parameter
    ref class G2{};
    

Contoh

Contoh berikut menunjukkan penggunaan batasan untuk memanggil metode instans pada parameter jenis.

// generics_constraints_5.cpp
// compile with: /clr
using namespace System;

interface class IAge {
   int Age();
};

ref class MyClass {
public:
   generic <class ItemType> where ItemType : IAge
   bool isSenior(ItemType item) {
      // Because of the constraint,
      // the Age method can be called on ItemType.
      if (item->Age() >= 65)
         return true;
      else
         return false;
   }
};

ref class Senior : IAge {
public:
   virtual int Age() {
      return 70;
   }
};

ref class Adult: IAge {
public:
   virtual int Age() {
      return 30;
   }
};

int main() {
   MyClass^ ageGuess = gcnew MyClass();
   Adult^ parent = gcnew Adult();
   Senior^ grandfather = gcnew Senior();

   if (ageGuess->isSenior<Adult^>(parent))
      Console::WriteLine("\"parent\" is a senior");
   else
      Console::WriteLine("\"parent\" is not a senior");

   if (ageGuess->isSenior<Senior^>(grandfather))
      Console::WriteLine("\"grandfather\" is a senior");
   else
      Console::WriteLine("\"grandfather\" is not a senior");
}
"parent" is not a senior
"grandfather" is a senior

Ketika parameter jenis generik digunakan sebagai batasan, parameter tersebut disebut batasan jenis telanjang. Batasan jenis telanjang berguna ketika fungsi anggota dengan parameter jenisnya sendiri perlu membatasi parameter tersebut ke parameter jenis dari jenis yang berisi.

Dalam contoh berikut, T adalah batasan jenis telanjang dalam konteks Add metode .

Batasan jenis telanjang juga dapat digunakan dalam definisi kelas generik. Kegunaan batasan jenis telanjang dengan kelas generik terbatas karena pengkompilasi dapat mengasumsikan apa pun tentang batasan jenis telanjang kecuali bahwa ia berasal dari Object. Gunakan batasan jenis telanjang pada kelas generik dalam skenario di mana Anda ingin menerapkan hubungan pewarisan antara dua parameter jenis.

// generics_constraints_6.cpp
// compile with: /clr /c
generic <class T>
ref struct List {
   generic <class U>
   where U : T
   void Add(List<U> items)  {}
};

generic <class A, class B, class C>
where A : C
ref struct SampleClass {};

Lihat juga

Generik