Condividi tramite


Vincoli su parametri di tipo generico (C++/CLI)

In il tipo generico o nelle dichiarazioni di metodo, è possibile qualificare un parametro di tipo con vincoli.Un vincolo è una condizione che i tipi utilizzato come argomenti di tipo devono soddisfare.Ad esempio, un vincolo è probabile che l'argomento di tipo deve implementare una determinata interfaccia o ereditare da una classe specifica.

I vincoli sono facoltativi, non specificare un vincolo su un parametro equivale a vincolare il parametro a Object.

where type-parameter: constraint list

Parametri

  • parametro di tipo
    Uno dei parametri di tipo, essere vincolato.

  • elenco di vincoli
    elenco di vincoli è un elenco delimitato da virgole di specifiche del vincolo.L'elenco può includere le interfacce da implementare dal parametro di tipo.

    L'elenco può includere anche la classe.Per l'argomento di tipo soddisfa un vincolo della classe base, sia la stessa classe del vincolo o derivare dal vincolo.

    È inoltre possibile specificare gcnew() per indicare che l'argomento di tipo deve disporre di un costruttore pubblico senza parametri; o ref class per indicare l'argomento di tipo deve essere un tipo di riferimento, incluse le classi, interfacce, delegati, o un tipo di matrice, o value class per indicare l'argomento di tipo deve essere un tipo di valore.Qualsiasi tipo di valore tranne nullable<t> può essere specificato.

    È inoltre possibile specificare un parametro generico come vincolo.L'argomento di tipo fornito per il tipo che si sta vincolo necessario che appartenga o derivare dal tipo di vincolo.Si tratta di un vincolo di tipo naked.

Note

La clausola di vincolo è costituito da where seguito da un parametro di tipo, dai due punti (:) e dal vincolo, che specifica la natura di restrizione per il parametro di tipo.where è una parola chiave sensibile al contesto, vedere Parole chiave sensibili al contesto (Estensioni del componente C++) per ulteriori informazioni.Più clausole separate di where con uno spazio.

I vincoli vengono applicati ai parametri di tipo per posizionare le limitazioni dei tipi che possono essere utilizzate come argomenti per un tipo o un metodo generico.

La classe e i vincoli specificare i tipi di argomento devono essere o ereditare da una classe specificata o implementare un'interfaccia specificata.

L'applicazione dei vincoli a un tipo generico o a un metodo consente al codice in quel tipo o metodo approfitti delle funzionalità nota dei tipi limitati.Ad esempio, è possibile dichiarare una classe generica in modo che i mezzi di parametro di tipo l'interfaccia di icomparable<t>:

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

Questo vincolo è necessario che un argomento di tipo utilizzato perT implementi IComparable<T> in fase di compilazione.Consente inoltre ai metodi di interfaccia, come CompareTo, vengano chiamati.Non esiste alcun cast necessario in un'istanza del parametro di tipo chiamare i metodi di interfaccia.

I metodi statici della classe dell' argomento di tipo non è possibile chiamare con il parametro di tipo; possono essere chiamati solo tramite il tipo effettivo denominato.

Un vincolo non può essere un tipo di valore, inclusi i tipi incorporati come int o double.Poiché i tipi di valore non possono avere classi derivate, una sola classe potrebbe non soddisfare il vincolo.In tal caso, l'oggetto generico può essere riscritto con il parametro di tipo sostituito dal tipo di valore specifico.

I vincoli sono in alcuni casi obbligatori poiché il compilatore non consente l'utilizzo di metodi o altre funzionalità di un tipo sconosciuto a meno che i vincoli implichino che il tipo sconosciuto supporti i metodi o le interfacce.

Più vincoli per lo stesso parametro di tipo possono essere specificati in un elenco delimitato da virgole

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

con i parametri di tipo più, utilizzare una clausola di where per ogni parametro di tipo.Di seguito è riportato un esempio:

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

Riepilogando, utilizzare vincoli nel codice in base alle regole seguenti:

  • Se più vincoli sono elencati, i vincoli possono essere visualizzati in qualsiasi ordine.

  • I vincoli possono essere tipi di classe, ad esempio classi di base astratta.tuttavia, i vincoli non possono essere tipi di valore o classi sealed.

  • I vincoli non possono essere stessi parametri di tipo, ma possono includere parametri di tipo in un tipo costruito aperto.Di seguito è riportato un esempio:

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

Esempio

In l ' esempio seguente viene illustrato l'utilizzo dei vincoli ai metodi di istanza di chiamata nei parametri di tipo.

// 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");
}
  

Quando un parametro di tipo generico viene utilizzato come vincolo, viene chiamato un vincolo di tipo naked.I vincoli di tipo naked sono utili quando una funzione membro con il relativo parametro di tipo necessario vincolare il parametro al parametro di tipo del tipo contenitore.

In l ' esempio seguente, T è un vincolo di tipo naked nel contesto del metodo Add.

I vincoli di tipo naked possono essere utilizzati nelle definizioni delle classi generiche.L'utilità dei vincoli di tipo naked con le classi generiche è limitata poiché il compilatore non può assumere non su un vincolo di tipo naked con la differenza che deriva da Object.Utilizzare vincoli di tipo naked sulle classi generiche negli scenari in cui si desidera applicare una relazione di ereditarietà tra due parametri di tipo.

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

Vedere anche

Altre risorse

Generics (Estensioni del componente C++)