c# .net generics c#-4.0

¿Por qué no hay varianza genérica para las clases en C#4.0?



.net generics (3)

Si lo tenemos para interfaces, ¿por qué no lo tenemos también para las clases? ¿Cuál sería el problema en el que incurriríamos al usarlo?



El equipo de .NET junto con el equipo de C # y VB.NET tiene recursos limitados, el trabajo que han realizado sobre co y contravariancia resuelve la mayor parte del problema del mundo real . Los sistemas de tipo son muy complejos para hacerlo bien: una solución que funciona en el 99.9999% de los casos no es lo suficientemente buena si conduce a códigos inseguros en los demás casos.

No creo que el costo / tiempo de soporte de las especificaciones de co y contravariancia (por ejemplo, "in / out") en los métodos de clase sea de un valor suficientemente grande. Puedo ver muy pocos casos en los que podrían ser utilizables, debido a la falta de herencia de clase multiplicada.

¿Prefieres haber esperado otros 6 meses para .net para obtener este soporte?

Otra forma de pensar en esto es en .net

  • Interfaces / delegados: se utilizan para modelar el sistema de tipo conceptual de una aplicación
  • Clase se utilizan para implementar los tipos anteriores
  • La herencia de clase se usa para reducir la duplicación de código mientras se hace lo anterior
  • co y contravariancia es sobre el sistema de tipo conceptual de una aplicación

Supongamos que tiene una clase C<T> que era covariante en T. ¿Cómo podría ser su implementación? T tiene que estar fuera solo. Eso significa que C<T> no puede tener ningún método que tome una T, ninguna propiedad de tipo T con un setter o cualquier campo de tipo T , porque los campos son lógicamente los mismos que los establecedores de propiedades; T entra.

Prácticamente lo único que se puede construir con una clase covariante es algo inmutable en lo que se refiere a T. Ahora, creo que sería increíble tener listas y pilas inmutables covariantes y todo lo demás, tipos de clases. Pero esa característica no es tan obviamente asombrosa que justificaría claramente el gasto masivo al hacer que el sistema tipo soporte de forma nativa tipos de clases inmutables covariantes.

Un comentario anterior solicitó un ejemplo de dónde esto sería útil. Considera el siguiente boceto:

sealed class Stack<out T> { private readonly T head; private readonly Stack<T> tail; public T Peek() { return head; } public Stack<T> Pop() { return tail; } public Stack(T head, Stack<T> tail) { this.tail = tail; this.head = head; } } static class StackExtensions { public static Stack<T> Push<T>(this Stack<T> tail, T head) { return new Stack<T>(head, tail); } public static bool IsEmpty<T>(this Stack<T> stack) { return stack == null; } }

Supongamos que tiene clases covariantes. Ahora puedes decir

Stack<string> strings = null; strings = strings.Push("hello"); strings = strings.Push("goodbye"); Stack<object> objects = strings; objects = objects.Push(123);

Y, oye, simplemente insertamos un número entero en una pila de cadenas, ¡pero todo salió bien! No hay ninguna razón por la cual esto no pueda ser seguro. Una operación que violaría la seguridad de tipo en una estructura de datos mutable puede ser covariante de forma segura en una estructura de datos inmutables.