Compartir a través de


Resolución de errores y advertencias relacionados con parámetros de tipo genérico y argumentos de tipo genérico

En este artículo se tratan los siguientes errores del compilador:

  • CS0080: no se permiten restricciones en declaraciones no genéricas.
  • CS0081: la declaración de parámetro de tipo debe ser un identificador, no un tipo.
  • CS0224: un método con vararg no puede ser genérico, estar en un tipo genérico o tener un parámetro params.
  • CS0304: no se puede crear una instancia del tipo de variable porque no tiene la new() restricción .
  • CS0305: El uso del tipo genérico requiere argumentos de tipo N.
  • CS0306: es posible que el tipo no se use como argumento de tipo.
  • CS0307: el identificador no es un método genérico. Si ha pensado en una lista de expresiones, use paréntesis alrededor de la expresión.
  • CS0308: el tipo o método no genérico no se puede usar con argumentos de tipo.
  • CS0310: el tipo debe ser un tipo no abstracto con un constructor público sin parámetros para usarlo como parámetro en el tipo o método genéricos.
  • CS0311: el tipo no se puede usar como parámetro T de tipo en el método o el tipo genérico. No hay ninguna conversión de referencia implícita de type1 a type2.
  • CS0312: el tipo 'type1' no se puede usar como parámetro de tipo en el tipo genérico o método. El tipo que acepta valores NULL 'type1' no satisface la restricción.
  • CS0313: El tipo 'type1' no se puede usar como parámetro de tipo en el tipo genérico o método. El tipo que acepta valores NULL 'type1' no satisface la restricción. Los tipos que aceptan valores NULL no pueden satisfacer ninguna restricción de interfaz.
  • CS0314: el tipo no se puede usar como parámetro de tipo en el tipo genérico o método. No hay conversión boxing ni conversión de parámetros de tipo.
  • CS0315: el tipo no se puede usar como parámetro T de tipo en el método o el tipo genérico. No hay ninguna conversión boxing.
  • CS0401: la new() restricción debe ser la última restricción especificada.
  • CS0403: no se puede convertir null al parámetro de tipo porque podría ser un tipo de valor que no acepta valores NULL. Considere la posibilidad de usar default(T) en su lugar.
  • CS0405: restricción duplicada para el parámetro de tipo.
  • CS0412: Parámetro: un parámetro, una variable local o una función local no puede tener el mismo nombre que un parámetro de tipo de método.
  • CS0413: el parámetro type no se puede usar con el as operador porque no tiene una restricción de tipo de clase ni una class restricción.
  • CS0417: Identificador: no puede proporcionar argumentos al crear una instancia de un tipo de variable.
  • CS0449: las classrestricciones , struct, unmanaged, notnully default no se pueden combinar ni duplicar y deben especificarse primero en la lista de restricciones.
  • CS0450: Parámetro de tipo: no se pueden especificar ambos, una clase de restricción y la restricción class o struct.
  • CS0451: la new() restricción no se puede usar con la struct restricción .
  • CS0454: dependencia de restricción circular que implica el parámetro de tipo 1 y el parámetro de tipo 2.
  • CS0455: el parámetro type hereda restricciones conflictivas.
  • CS0694: el parámetro Type tiene el mismo nombre que el tipo o método contenedor.
  • CS0695: T no puede implementar ambas interfaces porque pueden unificarse para algunas sustituciones de parámetros de tipo.
  • CS0698: Un tipo genérico no puede derivar del tipo porque es una clase de atributo.
  • CS0702: La restricción no puede ser una clase especial.
  • CS0703: Accesibilidad incoherente: el tipo de restricción es menos accesible que la declaración.
  • CS0706: tipo de restricción no válido. Un tipo usado como restricción debe ser una interfaz, una clase no sellada o un parámetro de tipo.
  • CS0717: Clase estática: las clases estáticas no se pueden usar como restricciones.
  • CS1961: Varianza no válida: el parámetro de tipo debe ser válidamente variante en el tipo.
  • CS7002: uso inesperado de un nombre genérico.
  • CS8322: no se puede pasar el argumento con tipo dinámico a una función local genérica con argumentos de tipo inferido.
  • CS9011: La palabra clave delegate no se puede usar como restricción. ¿Quieres decir System.Delegate?
  • CS9012: palabra clave recordinesperada . ¿Quieres decir record struct o record class?
  • CS9338: Accesibilidad incoherente: el tipo es menos accesible que la clase .

Declaración y nomenclatura de parámetros de tipo

Los errores siguientes se relacionan con la forma en que se declaran los parámetros de tipo y nombre en los métodos y tipos genéricos:

  • CS0080: no se permiten restricciones en declaraciones no genéricas.
  • CS0081: la declaración de parámetro de tipo debe ser un identificador, no un tipo.
  • CS0412: Parámetro: un parámetro, una variable local o una función local no puede tener el mismo nombre que un parámetro de tipo de método.
  • CS0694: el parámetro Type tiene el mismo nombre que el tipo o método contenedor.
  • CS9012: palabra clave recordinesperada . ¿Quieres decir record struct o record class?

Para corregir estos errores, asegúrese de declarar parámetros de tipo con identificadores válidos, aplicar cláusulas de restricción solo a declaraciones genéricas y evitar conflictos de nomenclatura con otros identificadores en el ámbito:

  • Quite la cláusula constraint de las declaraciones no genéricas (CS0080). La where cláusula solo se puede usar en tipos y métodos genéricos que declaran parámetros de tipo, ya que las restricciones definen los requisitos que deben cumplir los argumentos de tipo. Si necesita aplicar restricciones, agregue primero parámetros de tipo a la declaración de tipo o método. Por ejemplo, cambia public class MyClass where MyClass : System.IDisposable a public class MyClass<T> where T : System.IDisposable.
  • Reemplace los nombres de tipo reales por identificadores en declaraciones de parámetros de tipo (CS0081). Debe declarar parámetros de tipo mediante identificadores (como T, TKeyo TValue) en lugar de tipos concretos (como int o string). El propósito de un parámetro de tipo es servir como marcador de posición que el compilador sustituye por tipos reales cuando se usa el tipo o método genéricos. Por ejemplo, cambia public void F<int>() a public void F<T>().
  • Cambie el nombre de los parámetros de tipo, las variables locales o los parámetros para evitar conflictos de nomenclatura (CS0412, CS0694). Los nombres de parámetro de tipo no pueden sombrear identificadores en el mismo ámbito. No pueden coincidir con el nombre del tipo o del método que lo contiene. Estos conflictos crean ambigüedad sobre el identificador al que se hace referencia. Por ejemplo, si tiene un método public void F<T>(), no puede declarar una variable double T local dentro de ese método y no puede asignar un nombre a un parámetro de tipo igual que su tipo contenedor (class C<C>).
  • Use la sintaxis de declaración de registro correcta (CS9012). Al declarar un tipo de registro, debe usar o record class o record struct (o simplemente record para un tipo de referencia). La record palabra clave solo no puede aparecer en posiciones donde el compilador espera una sintaxis de declaración de tipo. Por ejemplo, si pretende declarar un tipo de registro, escribir record class MyRecord o record struct MyRecord en lugar de colocar record donde se espera una palabra clave diferente.

Para obtener más información, vea Parámetros de tipo genérico y genéricos.

Declaración y ordenación de restricciones

Los errores siguientes se relacionan con la sintaxis y el orden de las restricciones en los parámetros de tipo genérico:

  • CS0401: la new() restricción debe ser la última restricción especificada.
  • CS0449: las classrestricciones , struct, unmanaged, notnully default no se pueden combinar ni duplicar y deben especificarse primero en la lista de restricciones.
  • CS0450: Parámetro de tipo: no se puede especificar simultáneamente ambos, una clase de restricción y la restricción class o struct.
  • CS0451: la new() restricción no se puede usar con la struct restricción .
  • CS9011: La palabra clave delegate no se puede usar como restricción. ¿Quieres decir System.Delegate?

Las restricciones de los parámetros de tipo deben seguir un orden específico: las restricciones principales (class, struct, unmanaged, notnullo default) vienen primero, seguidas de restricciones de interfaz o clase y, por último, la new() restricción de constructor. Algunas restricciones son mutuamente excluyentes y no se pueden combinar.

Para corregir estos errores:

  • Coloque la new() restricción al final de la lista de restricciones (CS0401). La new() restricción debe aparecer después de todas las demás restricciones. Por ejemplo, cambia where T : new(), IDisposable a where T : IDisposable, new().
  • Coloque primero las restricciones principales y no combine restricciones mutuamente excluyentes (CS0449). Puede especificar como máximo uno de class, struct, unmanaged, notnull o default, y debe aparecer en primer lugar en la lista de restricciones. Las class restricciones y struct son mutuamente excluyentes, como son class y unmanaged. En un contexto que acepta valores NULL, class ya implica notnull, por lo que no se pueden combinar.
  • No combine una restricción de clase específica con struct (CS0450). Si un parámetro de tipo está restringido a un tipo de clase específico, es implícitamente un tipo de referencia, que contradiga la struct restricción. Quite la restricción de clase o la restricción struct.
  • No combine new() con struct (CS0451). Todos los tipos de valor (structs) tienen implícitamente un constructor sin parámetros público, por lo que la new() restricción es redundante cuando se combina con struct. Quite la new() restricción al usar struct.
  • Reemplace por delegateSystem.Delegate en cláusulas de restricción (CS9011). La delegate palabra clave se usa para declarar tipos delegados, no como una restricción. Para restringir un parámetro de tipo a los tipos delegados, use System.Delegate como tipo de restricción. Por ejemplo, cambia where T : delegate a where T : System.Delegate.

En el ejemplo siguiente se muestra la ordenación de restricciones correcta:

using System;

// Primary constraint first, then interface constraints, then new()
class C<T> where T : class, IDisposable, new() { }

// struct doesn't need new() - it's implicit
class D<T> where T : struct, IComparable { }

// Delegate constraint using System.Delegate
class E<T> where T : System.Delegate { }

Para obtener más información, vea Restricciones de tipos de parámetros.

Recuento y uso de argumentos de tipo

Los siguientes errores se relacionan con proporcionar el número y el tipo correctos de argumentos de tipo a los tipos y métodos genéricos:

  • CS0224: un método con vararg no puede ser genérico, estar en un tipo genérico o tener un parámetro params.
  • CS0305: El uso del tipo genérico requiere argumentos de tipo N.
  • CS0306: es posible que el tipo no se use como argumento de tipo.
  • CS0307: el identificador no es un método genérico. Si ha pensado en una lista de expresiones, use paréntesis alrededor de la expresión.
  • CS0308: el tipo o método no genérico no se puede usar con argumentos de tipo.
  • CS7002: uso inesperado de un nombre genérico.

Para corregir estos errores, asegúrese de proporcionar el número exacto de argumentos de tipo requeridos por la declaración genérica. Use solo tipos válidos como argumentos de tipo. No aplique argumentos de tipo a construcciones no genéricas:

  • Quite parámetros de tipo genérico o que contengan declaraciones de tipos genéricos de métodos que usan __arglist (CS0224). La __arglist palabra clave no es compatible con los genéricos porque los mecanismos en tiempo de ejecución para controlar las listas de argumentos variables entran en conflicto con la sustitución de tipos necesaria para los parámetros de tipo genérico. Esta restricción también se aplica a la params palabra clave cuando se usa en combinación con métodos o métodos genéricos dentro de tipos genéricos.
  • Proporcione el número exacto de argumentos de tipo especificados en la declaración de tipo o método genérico (CS0305). Cada parámetro de tipo genérico declarado en la definición debe tener un argumento de tipo correspondiente cuando se crea una instancia del tipo genérico. El compilador debe saber qué tipo concreto sustituir por cada parámetro de tipo. Por ejemplo, si una clase se declara como class MyList<T>, debe proporcionar exactamente un argumento de tipo al usarlo, como MyList<int>, no MyList<int, string>.
  • Use solo tipos válidos como argumentos de tipo (CS0306). Los tipos de puntero, como int* o char*, no se pueden usar como argumentos de tipo porque los tipos genéricos requieren tipos administrados que el recolector de basura pueda seguir, y los tipos de puntero no son administrados. Si necesita trabajar con punteros en un contexto genérico, considere la posibilidad de usar IntPtr o reestructurar el código para evitar mezclar genéricos con código no seguro.
  • Quite la sintaxis del argumento de tipo de las construcciones no genéricas (CS0307, CS0308). Los argumentos de tipo entre corchetes angulares (como <int>) solo se pueden aplicar a tipos genéricos y métodos que declaran parámetros de tipo. Debe quitar completamente los argumentos de tipo o asegurarse de importar el espacio de nombres que contiene la versión genérica del tipo. Por ejemplo, IEnumerator<T> requiere la using System.Collections.Generic; directiva , mientras que IEnumerator está en System.Collections.
  • Quite los parámetros de tipo de las declaraciones que no admiten genéricos (CS7002). Algunas construcciones, como enumeraciones, no pueden ser genéricas. Si necesita un contenedor genérico para los valores de enumeración, considere la posibilidad de usar una clase o estructura genérica en su lugar.

Para obtener más información, vea Parámetros de tipo genérico y genéricos.

Restricciones de constructor

Los errores siguientes se relacionan con la new() restricción en los parámetros de tipo genérico:

  • CS0304: no se puede crear una instancia del tipo de variable porque no tiene la new() restricción .
  • CS0310: el tipo debe ser un tipo no abstracto con un constructor público sin parámetros para usarlo como parámetro en el tipo o método genéricos.
  • CS0417: Identificador: no puede proporcionar argumentos al crear una instancia de un tipo de variable.

Para corregir estos errores, agregue la new() restricción a los parámetros de tipo que se deben crear instancias, asegúrese de que los argumentos de tipo tengan constructores sin parámetros públicos y evite pasar argumentos al construir instancias de parámetros de tipo:

  • Agregue la new() restricción a la declaración de parámetro de tipo (CS0304). Cuando se usa el new operador para crear una instancia de un parámetro de tipo dentro de un tipo genérico o método, el compilador debe poder garantizar que cualquier argumento de tipo proporcionado en tiempo de ejecución tenga disponible un constructor sin parámetros. La new() restricción proporciona esta garantía en tiempo de compilación, lo que permite al compilador generar el código de creación de instancias adecuado. Por ejemplo, si tiene class C<T> con un miembro T t = new T();, debe cambiar la declaración a class C<T> where T : new().
  • Asegúrese de que los argumentos de tipo usados con new() parámetros de tipo restringido tienen constructores sin parámetros públicos (CS0310). Cuando un tipo o método genérico declara una new() restricción en un parámetro de tipo, cualquier tipo concreto usado como argumento de tipo debe ser no abstracto y debe proporcionar un constructor público sin parámetros. Si un tipo solo tiene constructores no públicos (como private o protected constructores) o solo tiene constructores con parámetros, no puede satisfacer la new() restricción. Para corregir este error, agregue un constructor público sin parámetros al tipo o use un argumento de tipo diferente que ya tenga uno.
  • Quite argumentos de constructor al crear instancias de parámetros de tipo (CS0417). La new() restricción solo garantiza la existencia de un constructor sin parámetros, por lo que no se pueden pasar argumentos a new T(arguments) porque el compilador no puede comprobar que existe un constructor con esos tipos de parámetros específicos en los tipos que se sustituyen por T. Si necesita construir instancias con argumentos específicos, considere la posibilidad de usar métodos de fábrica, patrones de fábrica abstractos o restricciones de interfaz o clase base específicas que definen el comportamiento de construcción que necesita.

Para obtener más información, vea Restricciones en los parámetros de tipo y la new() restricción .

Resolución y conversiones de restricciones

Los errores siguientes se relacionan con los argumentos de tipo que no satisfacen las restricciones de los parámetros de tipo genérico:

  • CS0311: el tipo no se puede usar como parámetro T de tipo en el método o el tipo genérico. No hay ninguna conversión de referencia implícita.
  • CS0312: el tipo no se puede usar como parámetro de tipo en el método o el tipo genérico. El tipo que acepta valores NULL no satisface la restricción.
  • CS0313: el tipo no se puede usar como parámetro de tipo en el tipo genérico o método. El tipo que acepta valores NULL no satisface la restricción. Los tipos que aceptan valores NULL no pueden satisfacer ninguna restricción de interfaz.
  • CS0314: el tipo no se puede usar como parámetro de tipo en el tipo genérico o método. No hay conversión boxing ni conversión de parámetros de tipo.
  • CS0315: el tipo no se puede usar como parámetro T de tipo en el tipo genérico o método TypeorMethod<T>. No hay ninguna conversión boxing.

Para corregir estos errores, use argumentos de tipo que cumplan todas las restricciones a través de las conversiones adecuadas, asegúrese de que las clases derivadas repitan restricciones de clase base y comprendan que los tipos de valor que aceptan valores NULL tienen requisitos de restricción especiales:

  • Cambie el argumento de tipo a uno que tenga una conversión de referencia implícita al tipo de restricción (CS0311). Cuando un parámetro de tipo tiene una restricción como where T : BaseType, cualquier argumento de tipo debe convertirse a BaseType través de una conversión de referencia implícita o conversión de identidad. El argumento de tipo debe ser BaseType propio, derivar de BaseTypeo implementar BaseType si es una interfaz. Las conversiones numéricas implícitas (como de short a int) no satisfacen restricciones de parámetros de tipo genérico porque estas conversiones son conversiones de valor, no conversiones de referencia.
  • Repita las restricciones de parámetro de tipo de la clase base en cualquier declaración de clase derivada (CS0314). Cuando una clase genérica derivada hereda de una clase genérica base que tiene restricciones en sus parámetros de tipo, la clase derivada debe declarar las mismas restricciones en sus parámetros de tipo correspondientes. Debe repetir estas restricciones porque el compilador debe comprobar que los argumentos de tipo proporcionados a la clase derivada cumplen los requisitos de la clase base. Por ejemplo, si tiene public class A<T> where T : SomeClass, cualquier clase derivada de ella debe declararse como public class B<T> : A<T> where T : SomeClass.
  • Use tipos de valor que no aceptan valores NULL o cambie el tipo de restricción (CS0312, CS0313). Los tipos de valor que aceptan valores NULL (como int?) son distintos de sus tipos de valor subyacentes y no satisfacen las mismas restricciones. No hay ninguna conversión implícita entre int? y inty , y los tipos de valor que aceptan valores NULL no pueden satisfacer las restricciones de interfaz porque el propio contenedor que acepta valores NULL no implementa la interfaz, aunque el tipo de valor subyacente sí lo haga. Para corregir estos errores, use la forma no anulable del tipo de valor como argumento de tipo, o ajuste la restricción para aceptar object o un tipo de referencia anulable si procede.
  • Asegúrese de que los argumentos de tipo satisfacen las restricciones de clase o tipo de referencia (CS0315). Cuando un parámetro de tipo está restringido a un tipo de clase (como where T : SomeClass), no se puede usar un tipo de valor (struct) como argumento de tipo porque no hay ninguna conversión boxing que satisfaga la relación de restricción. La restricción requiere un tipo de referencia que tenga una relación de herencia o implementación con el tipo de restricción. Para resolver este error, cambie la estructura a una clase si es adecuada semánticamente o quite la restricción de clase si el tipo genérico puede funcionar con tipos de valor.

Para obtener más información, vea Restricciones en parámetros de tipo y conversiones implícitas.

Restricciones de uso de tipos genéricos

Los errores siguientes se relacionan con las restricciones sobre cómo se pueden usar los tipos genéricos:

  • CS0403: no se puede convertir null al parámetro de tipo porque podría ser un tipo de valor que no acepta valores NULL. Considere la posibilidad de usar default(T) en su lugar.
  • CS0413: el parámetro type no se puede usar con el as operador porque no tiene una restricción de tipo de clase ni una class restricción.
  • CS0695: El tipo no puede implementar ambas interfaces y porque pueden unificarse para algunas sustituciones de parámetros de tipo.
  • CS0698: Un tipo genérico no puede derivar del tipo porque es una clase de atributo.
  • CS8322: no se puede pasar el argumento con tipo dinámico a una función local genérica con argumentos de tipo inferido.
  • CS9338: Accesibilidad incoherente: el tipo es menos accesible que la clase .

Para corregir estos errores, use default en lugar de null para parámetros de tipo sin restricciones, agregue restricciones de clase al usar el as operador, evite conflictos de unificación de interfaz, no cree clases de atributos genéricos y asegúrese de que los argumentos de tipo coinciden con la visibilidad de sus miembros contenedores:

  • Reemplace null las asignaciones por default(T) o agregue una class restricción (CS0403). Cuando se asigna null a un parámetro de tipo sin restricciones, el compilador no puede garantizar que el argumento type sea un tipo de referencia que acepte null valores, ya que podría ser un tipo de valor como int o struct, que no puede ser null. Para resolver este error, use default(T), que proporciona el valor predeterminado adecuado para cualquier tipo (null para los tipos de referencia, cero o vacío para los tipos de valor), o agregue una class restricción al parámetro de tipo si necesita específicamente semántica de tipos de referencia y desea permitir null asignaciones.
  • Agregue una class restricción de tipo o específica al usar el as operador (CS0413). El as operador realiza una conversión de tipos seguros que devuelve null si se produce un error en la conversión, pero este comportamiento no es compatible con los tipos de valor porque los tipos de valor no pueden ser null. Cuando se usa as con un parámetro de tipo sin restricciones, el compilador no puede garantizar que el argumento de tipo no sea un tipo de valor, por lo que rechaza el código. Para corregir este error, agregue una class restricción o una restricción de tipo de referencia específica (como where T : SomeClass) para asegurarse de que el parámetro de tipo siempre es un tipo de referencia que pueda controlar correctamente el null resultado de una conversión con errores.
  • Evite implementar la misma interfaz genérica varias veces con parámetros de tipo que podrían unificar (CS0695). Cuando una clase implementa una interfaz genérica varias veces con distintos parámetros de tipo (como class G<T1, T2> : I<T1>, I<T2>), existe el riesgo de que alguien pueda crear una instancia de él con el mismo tipo para ambos parámetros (G<int, int>), lo que crearía un conflicto porque la clase estaría implementando I<int> dos veces. Para resolver este error, implemente la interfaz una sola vez, reestructure los parámetros de tipo para evitar la unificación o use clases no genéricas independientes para diferentes especializaciones.
  • Quite los parámetros de tipo genérico de las clases de atributo (CS0698).

    Nota:

    Este error no se produce en las versiones actuales de C#, ya que ahora se admiten atributos genéricos.

  • Especifique explícitamente argumentos de tipo al pasar valores dinámicos a funciones locales genéricas (CS8322). Cuando se pasa un dynamic argumento a una función local genérica, el compilador no puede deducir argumentos de tipo porque el tipo real no se conoce hasta el tiempo de ejecución. Para corregir este error, especifique explícitamente el argumento type (por ejemplo, LocalFunc<int>(d)), convierta el valor dinámico en el tipo esperado o use una variable no dinámica.
  • Asegúrese de que los argumentos de tipo usados en firmas públicas o protegidas son al menos tan accesibles como el miembro que los usa (CS9338). Un miembro genérico público o protegido debe usar argumentos de tipo accesibles públicamente. De lo contrario, el código externo no pudo hacer referencia correctamente ni usar la firma del miembro. Por ejemplo, si tiene public class Container<T> donde T es un tipo interno, los ensamblados externos pueden ver el Container pero no pueden trabajar correctamente con él porque no pueden ver T. Para corregir este error, haga público el argumento de tipo o reduzca la accesibilidad del miembro que lo usa para que coincida con la accesibilidad del argumento de tipo.

Para obtener más información, vea Restricciones en parámetros de tipo, expresiones de valor predeterminadas y Atributos.

Tipos de restricciones válidos

Los errores siguientes se relacionan con el uso de tipos no válidos como restricciones en parámetros de tipo genérico:

  • CS0405: restricción duplicada para el parámetro de tipo.
  • CS0702: La restricción no puede ser una clase especial.
  • CS0703: Accesibilidad incoherente: el tipo de restricción es menos accesible que la declaración.
  • CS0706: tipo de restricción no válido. Un tipo usado como restricción debe ser una interfaz, una clase no sellada o un parámetro de tipo.
  • CS0717: static class: las clases estáticas no se pueden usar como restricciones.

Una restricción debe ser una interfaz, una clase no sellada o un parámetro de tipo. Algunos tipos no son válidos como restricciones debido a su significado especial en el sistema de tipos de .NET o porque no se pueden heredar.

Para corregir estos errores:

  • Quite las restricciones duplicadas (CS0405). Cada restricción solo puede aparecer una vez en una cláusula de restricción. Si tiene where T : I, I, elimine el duplicado.
  • No use clases especiales como restricciones (CS0702). Los tipos Object, Arrayy ValueType no se pueden usar como restricciones. Todos los tipos ya derivan de Object, por lo que restringirlo no proporciona ningún valor. Array y ValueType son tipos base abstractos que no se pueden heredar directamente. Si necesita un comportamiento similar a la matriz, use IList<T> o IEnumerable<T> en su lugar.
  • Asegúrese de que los tipos de restricción sean al menos tan accesibles como el tipo genérico (CS0703). Un tipo genérico público no puede tener restricciones mediante tipos internos, ya que el código externo no podría proporcionar argumentos de tipo válidos. Haga que el tipo de restricción sea público o reduzca la accesibilidad del tipo genérico.
  • Use solo interfaces, clases no selladas o parámetros de tipo como restricciones (CS0706). No puede usar matrices, clases selladas, estructuras, enumeraciones u otros tipos no válidos como restricciones. Si necesita un comportamiento específico, considere la posibilidad de usar una interfaz que implementan los tipos deseados.
  • No use clases estáticas como restricciones (CS0717). Las clases estáticas no se pueden extender porque solo contienen miembros estáticos. No puede existir ningún tipo que derive de una clase estática, lo que hace que sea inútil como una restricción. En su lugar, use una interfaz o clase no estática.

En el ejemplo siguiente se muestran los tipos de restricción válidos:

public interface IMyInterface { }
public class MyBaseClass { }

// Valid: interface constraint
class A<T> where T : IMyInterface { }

// Valid: non-sealed class constraint
class B<T> where T : MyBaseClass { }

// Valid: type parameter constraint
class C<T, U> where T : U { }

Para obtener más información, vea Restricciones de tipos de parámetros.

Conflictos de restricciones y dependencias circulares

Los errores siguientes se relacionan con conflictos entre restricciones o dependencias circulares en declaraciones de restricciones:

  • CS0454: dependencia de restricción circular que implica el parámetro de tipo 1 y el parámetro de tipo 2.
  • CS0455: el parámetro type hereda restricciones conflictivas.

Las restricciones no pueden crear dependencias circulares y los parámetros de tipo no pueden heredar restricciones en conflicto que son imposibles de satisfacer simultáneamente.

Para corregir estos errores:

  • Quite las dependencias de restricciones circulares (CS0454). Un parámetro de tipo no puede depender directa o indirectamente de sí mismo a través de sus restricciones. Por ejemplo, where T : U where U : T crea una dependencia circular porque T depende U de y U depende de T. Interrumpa el ciclo quitando una de las restricciones.
  • Quitar restricciones heredadas que entran en conflicto (CS0455). Un parámetro de tipo no se puede restringir a varias clases no relacionadas, ya que C# no admite la herencia de varias clases. Del mismo modo, no se puede restringir tanto a struct como a un tipo de clase, ya que estas restricciones son mutuamente excluyentes. Reestructure la jerarquía de tipos o elimine una de las restricciones en conflicto.

En el ejemplo siguiente se muestran los problemas:

// CS0454: Circular dependency - T depends on U and U depends on T
class Circular<T, U> where T : U where U : T { }

// CS0455: Conflicting constraints - U can't derive from both B and B2
public class B { }
public class B2 { }
public class G<T> where T : B
{
    public class N<U> where U : B2, T { }
}

Para obtener más información, vea Restricciones de tipos de parámetros.

Varianza del parámetro de tipo

El siguiente error se relaciona con los modificadores de varianza en los parámetros de tipo genérico:

  • CS1961: Varianza no válida: el parámetro de tipo debe ser correctamente variado en el tipo especificado.

Los modificadores de varianza (in para contravarianza, out para covarianza) controlan cómo se usan parámetros de tipo en declaraciones de interfaz y delegados. Un parámetro de tipo covariante (out) solo puede aparecer en posiciones de salida (tipos devueltos), mientras que un parámetro de tipo contravariante (in) solo puede aparecer en posiciones de entrada (tipos de parámetro).

Para corregir este error:

  • Use out (covariante) para los parámetros de tipo que solo aparecen en los tipos devueltos. La Covarianza permite usar un tipo más derivado en el que se espera un tipo menos derivado.
  • Use in (contravariante) para los parámetros de tipo que solo aparecen en tipos de parámetros. La contravarianza permite usar un tipo menos derivado donde se espera un tipo más derivado.
  • Quite el modificador de varianza si el parámetro de tipo debe aparecer en las posiciones de entrada y salida.

En el ejemplo siguiente se muestra el uso de varianza correcto e incorrecto:

// Incorrect: out T can't appear in input position
interface IWrong<out T>
{
    void Method(T arg);  // CS1961
}

// Correct: out T only in output positions
interface ICovariant<out T>
{
    T GetValue();
}

// Correct: in T only in input positions
interface IContravariant<in T>
{
    void Process(T arg);
}

// No modifier needed for both input and output
interface IInvariant<T>
{
    T Transform(T arg);
}

Para obtener más información, vea Covarianza y Contravarianza en Genéricos.