Restricciones de parámetros de tipo genérico (C++/CLI)Constraints on Generic Type Parameters (C++/CLI)

En las declaraciones de método o tipo genérico, puede calificar un parámetro de tipo con restricciones.In generic type or method declarations, you can qualify a type parameter with constraints. Una restricción es un requisito que deben satisfacer los tipos usados como argumentos de tipo.A constraint is a requirement that types used as type arguments must satisfy. Por ejemplo, una restricción podría ser que el argumento de tipo debe implementar una determinada interfaz o heredar de una clase específica.For example, a constraint might be that the type argument must implement a certain interface or inherit from a specific class.

Las restricciones son opcionales; no especificar una restricción sobre un parámetro es equivalente a restringir ese parámetro a Object.Constraints are optional; not specifying a constraint on a parameter is equivalent to constraining that parameter to Object.

SintaxisSyntax

where type-parameter: constraint list

ParámetrosParameters

parámetro de tipotype-parameter
Uno de los parámetros de tipo, que se va a restringir.One of the type parameters, to be constrained.

constraint listconstraint list
constraint list es una lista separada por comas de especificaciones de restricción.constraint list is a comma-separated list of constraint specifications. La lista puede incluir interfaces que se van a implementar por el parámetro de tipo.The list can include interfaces to be implemented by the type parameter.

La lista puede incluir también una clase.The list can also include a class. Para que el argumento de tipo satisfaga una restricción de clase base, debe ser de la misma clase que la restricción o derivarse de ella.For the type argument to satisfy a base class constraint, it must be the same class as the constraint or derive from the constraint.

También puede especificar gcnew() para indicar que el argumento de tipo debe tener un constructor público sin parámetros; o ref class para indicar que el argumento de tipo debe ser un tipo de referencia, incluido cualquier tipo de clase, interfaz, delegado o matriz; o value class para indicar que el tipo de argumento debe ser un tipo de valor.You can also specify gcnew() to indicate the type argument must have a public parameterless constructor; or ref class to indicate the type argument must be a reference type, including any class, interface, delegate, or array type; or value class to indicate the type argument must be a value type. Se puede especificar cualquier tipo de valor excepto Nullable <T> .Any value type except Nullable<T> can be specified.

También puede especificar un parámetro genérico como restricción.You can also specify a generic parameter as a constraint. El argumento de tipo proporcionado para el tipo que se va a restringir debe ser o derivarse del tipo de la restricción.The type argument supplied for the type you are constraining must be or derive from the type of the constraint. Esto se conoce como restricción de tipo "naked".This is called a naked type constraint.

ObservacionesRemarks

La cláusula de restricción consta de where seguido de un tipo de parámetro, dos puntos (:) y la restricción, que especifica la naturaleza de la restricción sobre el tipo de parámetro.The constraint clause consists of where followed by a type parameter, a colon (:), and the constraint, which specifies the nature of the restriction on the type parameter. where es una palabra clave contextual; para más información, consulte Palabras clave contextuales.where is a context-sensitive keyword; see Context-Sensitive Keywords for more information. Separe varias cláusulas where con un espacio.Separate multiple where clauses with a space.

Se aplican restricciones a parámetros de tipo para imponer limitaciones sobre los tipos que se pueden usar como argumentos con un tipo o método genérico.Constraints are applied to type parameters to place limitations on the types that can be used as arguments for a generic type or method.

Las restricciones de clase e interfaz especifican que los tipos de argumento deben ser o heredar de una clase especificada o implementar una interfaz especificada.Class and interface constraints specify that the argument types must be or inherit from a specified class or implement a specified interface.

La aplicación de restricciones a un tipo o método genérico permite que el código de ese tipo o método aproveche las ventajas de las características conocidas de los tipos restringidos.The application of constraints to a generic type or method allows code in that type or method to take advantage of the known features of the constrained types. Por ejemplo, se puede declarar una clase genérica como que el tipo de parámetro implementa la interfaz IComparable<T>:For example, you can declare a generic class such that the type parameter implements the IComparable<T> interface:

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

Esta restricción requiere que un argumento de tipo usado para T implemente IComparable<T> en tiempo de compilación.This constraint requires that a type argument used for T implements IComparable<T> at compile time. También permite la llamada a métodos de interfaz, como CompareTo.It also allows interface methods, such as CompareTo, to be called. Para llamar a métodos de interfaz, no hace falta ninguna conversión sobre una instancia del parámetro de tipo.No cast is needed on an instance of the type parameter to call interface methods.

Los métodos estáticos de la clase del argumento de tipo no se pueden llamar mediante el parámetro de tipo, sino solo mediante el tipo con nombre real.Static methods in the type argument's class cannot be called through the type parameter; they can be called only through the actual named type.

Una restricción no puede ser un tipo de valor, incluidos los tipos integrados como int o double .A constraint cannot be a value type, including built-in types such as int or double. Puesto que los tipos de valor no pueden tener clases derivadas, solo una clase podría satisfacer la restricción.Since value types cannot have derived classes, only one class would ever be able to satisfy the constraint. En ese caso, el genérico se puede reescribir con el parámetro de tipo reemplazado por el tipo de valor específico.In that case, the generic can be rewritten with the type parameter replaced by the specific value type.

En ocasiones, las restricciones son necesarias ya que el compilador no permitirá el uso de métodos u otras características de un tipo desconocido a menos que las restricciones impliquen que el tipo desconocido admite los métodos o interfaces.Constraints are required in some cases since the compiler will not allow the use of methods or other features of an unknown type unless the constraints imply that the unknown type supports the methods or interfaces.

Se pueden especificar varias restricciones para el mismo parámetro de tipo en una lista separada por comasMultiple constraints for the same type parameter can be specified in a comma-separated list

// 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 varios parámetros de tipo, use una cláusula where para cada uno.With multiple type parameters, use one where clause for each type parameter. Por ejemplo:For example:

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

En resumen, para usar restricciones en el código, siga las reglas siguientes:To summarize, use constraints in your code according to the following rules:

  • Si aparecen varias restricciones, estas pueden mostrarse en cualquier orden.If multiple constraints are listed, the constraints may be listed in any order.

  • Las restricciones también pueden ser tipos de clase, como clases base abstractas.Constraints can also be class types, such as abstract base classes. Sin embargo, las restricciones no pueden ser tipos de valor o clases selladas.However, constraints cannot be value types or sealed classes.

  • Las restricciones no pueden ser por sí solas parámetros de tipo, pero pueden estar relacionadas con ellos en un tipo construido abierto.Constraints cannot themselves be type parameters, but they can involve the type parameters in an open constructed type. Por ejemplo:For example:

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

EjemplosExamples

En el ejemplo siguiente se muestra cómo usar restricciones para llamar a métodos de instancia en parámetros de tipo.The following example demonstrates using constraints to call instance methods on type parameters.

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

Cuando se usa un parámetro de tipo genérico como restricción, esto se conoce como restricción de tipo "naked".When a generic type parameter is used as a constraint, it is called a naked type constraint. Las restricciones de tipo "naked" son útiles cuando una función miembro con su propio parámetro de tipo tiene que restringir ese parámetro al parámetro de tipo del tipo contenedor.Naked type constraints are useful when a member function with its own type parameter needs to constrain that parameter to the type parameter of the containing type.

En el ejemplo siguiente, T es una restricción de tipo "naked" en el contexto del método Add.In the following example, T is a naked type constraint in the context of the Add method.

Las restricciones de tipo "naked" también se pueden utilizar en definiciones de clase genéricas.Naked type constraints can also be used in generic class definitions. La utilidad de las restricciones de tipo "naked" con clases genéricas es limitada, ya que el compilador no puede dar por supuesto nada sobre la restricción de tipo "naked", excepto que se deriva de Object.The usefulness of naked type constraints with generic classes is limited because the compiler can assume nothing about a naked type constraint except that it derives from Object. Use restricciones de tipo "naked" sobre clases genéricas en situaciones en las que quiera aplicar una relación de herencia entre dos parámetros de tipo.Use naked type constraints on generic classes in scenarios in which you wish to enforce an inheritance relationship between two type parameters.

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

Vea tambiénSee also

GenéricosGenerics