2011-08-17 7 views
12

¿Es posible especificar una restricción en una clase genérica que no permite ciertos tipos? No sé si es posible y si lo es, no estoy seguro de cuál sería la sintaxis. Algo como:¿Cómo se especifican los tipos no permitidos en una restricción .NET Generics?

public class Blah<T> where : !string { 
} 

Parece que no puedo encontrar ninguna anotación que permita tal restricción.

+0

no creo que esto sea posible, pero ¿por qué necesitarías algo como esto? – Carsten

+0

¿Cuál es el comportamiento deseado cuando alguien intenta pasar un tipo que no es compatible? –

+0

De hecho, estaba tratando de excluir el tipo de cadena, pero resulta que usar T: struct funciona para lo que estoy tratando de hacer ya que mi clase no funcionará para tipos complejos de todos modos. –

Respuesta

11

Lo más cerca que puede obtener es una restricción de tiempo de ejecución.

Editar: Originalmente puse el control en tiempo de ejecución en la llamada del constructor. Eso en realidad no es óptimo, ya que incurre en gastos generales en cada instanciación; Creo que sería mucho más sensato para poner el cheque en el constructor estático, que se invoca una vez por tipo usado como parámetro T para su tipo Blah<T>:

public class Blah<T> { 
    static Blah() { 
     // This code will only run ONCE per T, rather than every time 
     // you call new Blah<T>() even for valid non-string type Ts 
     if (typeof(T) == typeof(string)) { 
      throw new NotSupportedException("The 'string' type argument is not supported."); 
     } 
    } 
} 

Obviamente no es ideal, pero si poner esta restricción en su lugar y documentar el hecho de que string no es un argumento de tipo compatible (por ejemplo, a través de comentarios XML), debe obtener en algún lugar cerca de la efectividad de una restricción en tiempo de compilación.

+1

normalmente pongo restricciones no expresables en C# en el constructor de clase. – CodesInChaos

+0

Para incluir el tipo que se puede resolver como una cadena: if (typeof (string) .IsAssignableFrom (typeof (T))) throw new NotSupportedException – Rasmus

4

No, no puede especificar directamente las restricciones de tipo "negadas".

+0

¿Hay un método indirecto, otro que algo como afirmar que el tipo de (T) no es algo? – SirPentor

+0

@SirPentor No como parte de la restricción de tipo, aunque podría hacer algo así en el código. – Donut

2

Restricciones solo pueden ser restricciones positivas, como se describe en el documentation.

La única cosa que puede hacer es especificar qué tipos puede ser puesto en el tipo genérico, pero no se puede especificar qué no se puede poner en ellos.

1

Estas son las limitaciones permitidas (more detail)

  • , donde T: struct
  • donde T: Clase
  • donde T: new()
  • donde T: [nombre de la clase de base]
  • donde T: [nombre de interfaz]
  • donde T: U (El argumento de tipo proporcionado para T debe ser o derivar del argumento proporcionado para U)
Cuestiones relacionadas