¿Por qué C#(4.0) no permite co y contravarianza en los tipos de clase genéricos?
generics c#-4.0 (3)
¿Cuál es la verdadera razón de esa limitación? ¿Es solo trabajo lo que había que hacer? ¿Es conceptualmente difícil? ¿Es imposible?
Claro, uno no podía usar los parámetros de tipo en los campos, porque siempre son de lectura y escritura. Pero esa no puede ser la respuesta, ¿verdad?
El motivo de esta pregunta es que estoy escribiendo un artículo sobre el soporte de la varianza en C # 4, y creo que debería explicar por qué está restringido a los delegados e interfaces. Solo para invertir la carga de la prueba.
Actualización: Eric preguntó por un ejemplo.
¿Qué hay de esto (no sé si eso tiene sentido, sin embargo :-))
public class Lookup<out T> where T : Animal {
public T Find(string name) {
Animal a = _cache.FindAnimalByName(name);
return a as T;
}
}
var findReptiles = new Lookup<Reptile>();
Lookup<Animal> findAnimals = findReptiles;
La razón para tener eso en una clase podría ser el caché que se guarda en la clase en sí. Y, por favor, no le pongas nombres a tus diferentes tipos de mascotas.
Por cierto, esto me lleva a los parámetros de tipo opcionales en C # 5.0 :-)
Actualización 2: No estoy reclamando que el CLR y C # deberían permitir esto. Sólo tratando de entender lo que llevó a que no lo hace.
En primer lugar, como dice Tomás, no está soportado en el CLR.
Segundo, ¿cómo funcionaría eso? Supongamos que tienes
class C<out T>
{ ... how are you planning on using T in here? ... }
T solo se puede utilizar en posiciones de salida. Como se nota, la clase no puede tener ningún campo de tipo T porque el campo podría escribirse. La clase no puede tener ningún método que tome una T, porque son escrituras lógicas. Supongamos que tiene esta característica: ¿cómo la aprovecharía?
Esto sería útil para clases inmutables si pudiéramos, por ejemplo, hacer que sea legal tener un campo de solo lectura de tipo T; de esa manera, reduciríamos masivamente la posibilidad de que se escribiera incorrectamente. Pero es bastante difícil encontrar otros escenarios que permitan la variación de una manera segura.
Si tienes tal escenario, me encantaría verlo. Eso sería un punto para que algún día esto se implemente en el CLR.
ACTUALIZACIÓN: ver
¿Por qué no hay una variación genérica para las clases en C # 4.0?
para más información sobre esta pregunta.
Por lo que sé, esta característica no es compatible con CLR, por lo que agregar esto también requeriría un trabajo significativo en el lado de CLR. Creo que la co y contra-varianza para interfaces y delegados en realidad fue compatible con CLR antes de la versión 4.0, por lo que esta fue una extensión relativamente sencilla de implementar.
(¡El soporte de esta característica para las clases sería definitivamente útil, sin embargo!)
Si estuvieran permitidos, se podrían definir clases o estructuras útiles al 100% seguras para el tipo (sin tipografía interna) que fueran covariantes con respecto a su tipo T, si su constructor aceptaba uno o más proveedores de T o T. Podrían definirse clases o estructuras útiles, 100% seguras, que sean contrarias a la T si sus constructores aceptaran uno o más consumidores de T. No estoy seguro de que haya una gran ventaja de una clase sobre una interfaz, más allá de la posibilidad de usar "nuevo" en lugar de usar un método de fábrica estático (probablemente de una clase cuyo nombre es similar al de la interfaz), pero puedo Ciertamente veremos casos de uso por tener estructuras inmutables que soportan la covarianza.