Hay ciertas clases en el Marco que efectivamente transmiten características especiales a todos los tipos derivados de ellas, pero no poseen esas características en sí mismas . El CLR en sí mismo no impone ninguna prohibición contra el uso de esas clases como restricciones, pero los tipos genéricos restringidos a ellas no adquirirían las características no heredadas como lo harían los tipos concretos. Los creadores de C # decidieron que debido a que tal comportamiento podría confundir a algunas personas y no vieron ninguna utilidad en él, deberían prohibir tales restricciones en lugar de permitirles comportarse como lo hacen en CLR.
Si, por ejemplo, a uno se le permitiera escribir void CopyArray<T>(T dest, T source, int start, int count)
:; uno podría pasar dest
ya source
métodos que esperan un argumento de tipo System.Array
; Además, se obtendría la validación en tiempo de compilación de que dest
y source
eran los tipos de matriz compatibles, pero no se podría acceder a los elementos de la matriz utilizando el[]
operador.
La incapacidad de usar Array
como restricción es bastante fácil de evitar, ya void CopyArray<T>(T[] dest, T[] source, int start, int count)
que funcionará en casi todas las situaciones en las que funcionaría el método anterior. Sin embargo, tiene una debilidad: el método anterior funcionaría en el escenario en el que uno o ambos argumentos fueran de tipo System.Array
mientras se rechazan los casos en los que los argumentos son tipos de matrices incompatibles; agregar una sobrecarga donde ambos argumentos fueran de tipo System.Array
haría que el código aceptara los casos adicionales que debería aceptar, pero también haría que aceptara erróneamente los casos que no debería.
Encuentro molesta la decisión de prohibir la mayoría de las restricciones especiales. El único que tendría un significado semántico cero sería System.Object
[ya que si eso fuera legal como restricción, cualquier cosa lo satisfaría]. System.ValueType
probablemente no sería muy útil, ya que las referencias de tipo ValueType
no tienen mucho en común con los tipos de valor, pero podría tener algún valor plausiblemente en casos que involucren Reflection. Ambos System.Enum
y System.Delegate
tendrían algunos usos reales, pero como los creadores de C # no pensaron en ellos, están prohibidos sin una buena razón.