2012-01-04 8 views
36

Según el título, ¿es posible declarar restricciones de negación de tipo en C# 4?restricción genérica NOT donde T:! IEnumerable

+6

incluso si lo hubiera, ¿puede describir un caso de uso? –

+1

Es extraño observar que tiene tal requisito. solo puedes codificar contra el tipo T que sabes que pertenece a una familia de clase. ¿Cómo se puede codificar en genéricos de lo contrario? O no necesita genéricos en este caso o necesita revisar sus casos de uso. –

+2

el caso de uso de interés era permitir que las siguientes sobrecargas coexistieran 'void doIt (T what) {}' 'void doIt (IEnumerable cuál es) {}' - en este momento hay ambigüedad porque 'T 'en el primer método podría ser un' IEnumerable <> '(así que me gustaría especificar que' T' NO debe ser 'IEnumerable') ... – Cel

Respuesta

36

No, no existe tal concepto ni en C# ni en el CLR.

+0

¿Este concepto llegará a C# y/o CLR en el futuro? –

+0

@RandRandom: No he oído hablar de ningún plan para ello. –

0

No, pero sería posible comprobar con un "es" y luego manejarlo apropiadamente ...

1

Se utiliza una restricción para que pueda garantizar el tipo que utiliza tiene algunas propiedades/métodos/.. desea usar.

Un genérico con una restricción de negación de tipo no tiene ningún sentido, ya que no tiene sentido conocer la ausencia de algunas propiedades/métodos que no desea utilizar.

+0

obviamente no ha recibido el error: ## '' no puede implementar tanto '>' y '>' porque pueden unificarse para algunas sustituciones de parámetros de tipo ##. . ciertamente hay casos en los que se desea especificar que el genericstype2 no puede ser generictype4 –

+0

Pude trabajar alrededor de mi escenario usando una serie de clases abstractas que implementan una instancia de la interfaz similar y heredan la clase abstracta. Supongo así es como lo hace la Acción y así sucesivamente .. –

4

Por lo que sé, no es posible hacer eso.

Lo que puede hacer es algunas comprobaciones en tiempo de ejecución:

public bool MyGenericMethod<T>() 
{ 
    // if (T is IEnumerable) // don't do this 

    if (typeof(T).GetInterface("IEnumerable") == null) 
     return false; 

    // ... 

    return true; 
} 
+1

No puede usar 'es 'así - comprueba si un * objeto * es compatible con un tipo. –

+2

lo que quiere decir es 'if (typeof (T) == typeof (IEnumerable)) {}' – kev

0

un uso para esto sería un tipo de opción.

public class Option<A,B> 
where A : !B 
where B : !A 
{ 
    private readonly A a; 
    private readonly B b; 

    private Option(){} 

    public Option(A a) 
    { 
     this.a = a 
    } 

    public Option(B b) 
    { 
     this.b = b 
    } 
} 

la comprobación del tiempo de ejecución funcionaría, por supuesto, pero no tendría la ventaja de comprobar el tipo en tiempo de compilación.

2

me encontré a mi mismo tratando de poner en práctica el mismo caso mencionado en los comentarios:

void doIt<T>(IEnumerable<T> what) { } 
void doIt<T>(T whats) { } 

I exceptúan el siguiente código para hacer referencia al primer método:

doIt(new List<T>()); 

Pero es realmente hace referencia al segundo.

Una solución es fundido el argumento de la siguiente manera:

doIt(new List<T>().AsEnumerable<T>()); 

El molde puede estar escondido tras otra sobrecarga:

void doIt<T>(List<T> whats) { 
    doIt(whats.AsEnumerable<T>()); 
} 
Cuestiones relacionadas