Omezení parametrů obecného typu (C++/CLI)

V deklarací obecného typu nebo metody můžete kvalifikovat parametr typu s omezeními. Omezení je požadavek, který typy používané jako argumenty typu musí splňovat. Omezením může být například to, že argument typu musí implementovat určité rozhraní nebo dědit z konkrétní třídy.

Omezení jsou volitelná; nezadání omezení parametru je ekvivalentní použití Object omezení.

Syntaxe

where type-parameter : constraint-list

Parametry

type-parameter
Jeden z identifikátorů parametrů typu, které chcete omezit.

constraint-list
Seznam specifikací omezení oddělených čárkami. Seznam může obsahovat rozhraní, která mají být implementována type-parameter.

Seznam může také obsahovat třídu. Chcete-li splnit omezení základní třídy, musí být argument typu stejná třída jako omezení nebo odvozen z omezení. Určuje ref class , že argument typu musí být referenčním typem, včetně libovolného classtypu , interface, delegatenebo array typu. Určuje value class , že argument typu musí být typ hodnoty. Lze zadat libovolný typ hodnoty s výjimkou Nullable<T> .

Můžete také určit gcnew() , že argument typu musí mít veřejný konstruktor bez parametrů.

Jako omezení můžete také zadat obecný parametr. Argument typu zadaný pro typ, který omezujete, musí být nebo musí být odvozen od typu omezení. Tento parametr se nazývá omezení typu nahý.

Poznámky

Klauzule constraint se skládá z where parametru typu, dvojtečky (:) a omezení, které určuje povahu omezení parametru typu. where je kontextově citlivé klíčové slovo. Další informace najdete v tématu Klíčová slova citlivá na kontext. Oddělte více where klauzulí mezerou.

Omezení se použijí na parametry typu, které umisťují omezení typů, které lze použít jako argumenty pro obecný typ nebo metodu.

Omezení třídy a rozhraní určují, že typy argumentů musí být nebo dědit ze zadané třídy nebo implementovat zadané rozhraní.

Použití omezení obecného typu nebo metody umožňuje kódu v daném typu nebo metodě využívat známé funkce omezených typů. Můžete například deklarovat obecnou třídu tak, aby parametr typu implementuje IComparable<T> rozhraní:

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

Toto omezení vyžaduje, aby argument typu použitý pro T implementace IComparable<T> v době kompilace. Umožňuje také volat metody rozhraní, jako CompareToje například . K volání metod rozhraní není potřeba žádné přetypování instance parametru typu.

Statické metody ve třídě argumentu typu nelze volat prostřednictvím parametru typu; mohou být volána pouze prostřednictvím skutečného pojmenovaného typu.

Omezení nemůže být typ hodnoty, včetně předdefinovaných typů, jako int je nebo double. Vzhledem k tomu, že typy hodnot nemohou mít odvozené třídy, může omezení splňovat pouze jedna třída. V takovém případě lze obecný přepsat parametrem typu nahrazeným konkrétním typem hodnoty.

V některých případech jsou vyžadována omezení, protože kompilátor nepovolí použití metod nebo jiných funkcí neznámého typu, pokud omezení neznačí, že neznámý typ podporuje metody nebo rozhraní.

V seznamu oddělených čárkami lze zadat více omezení pro stejný parametr typu.

// 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 {};

U více parametrů typu použijte klauzuli where pro každý parametr typu. Příklad:

// 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 {};

Omezení v kódu použijte podle následujících pravidel:

  • Pokud je uvedeno více omezení, mohou být omezení uvedena v libovolném pořadí.

  • Omezení mohou být také typy tříd, jako jsou abstraktní základní třídy. Omezení však nemohou být typy hodnot ani sealed třídy.

  • Omezení samy o sobě nemohou být parametry typu, ale mohou zahrnovat parametry typu v otevřeném vytvořeném typu. Příklad:

    // 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{};
    

Příklady

Následující příklad ukazuje použití omezení pro volání metod instance u parametrů typu.

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

Pokud se jako omezení používá parametr obecného typu, nazývá se omezení typu nahý. Omezení holého typu jsou užitečná, když členová funkce s vlastním parametrem typu musí tento parametr omezit na parametr typu obsahujícího typu.

V následujícím příkladu T je omezení typu nahý v kontextu Add metody.

Omezení typu Nahý lze použít také v obecných definicích tříd. Užitečnost omezení holého typu s obecnými třídami je omezená, protože kompilátor nemůže předpokládat nic o omezení nahý typ s tím rozdílem, že je odvozen z Object. Omezení typu nahý použijte u obecných tříd ve scénářích, ve kterých chcete vynutit vztah dědičnosti mezi dvěma parametry typu.

// 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 {};

Viz také

Obecné typy