2011-01-08 8 views
15

Recientemente traté de crear una subclase genérica mediante la implementación de una interfaz genérica.¿Por qué necesito redeclarar la restricción de tipo en la subclase genérica

public interface IModule<T> where T : DataBean { ..... } 
public class Module<T> : IModule<T> where T : DataBean { .... } 

Parece que no puedo confiar en ninguna de las restricciones de T como se define en la interfaz base, y necesito que volver a declarar a mí mismo.

MSDN acaba de proporcionar:

Cuando se utiliza la subclase de tipo genérico parámetros, debe repetir ningún limitaciones estipuladas en el nivel de clase base a nivel de subclase. Para el ejemplo , restricción de derivación

¿Por qué no es posible inferir las restricciones de la clase base/interfaz?

+1

No es necesario copiar las restricciones, también puede optar por usar algo que sea convertible al tipo de restricción principal, lo que hará que el niño sea más especializado. –

+0

La especificación de C# 4.0 dice más o menos lo mismo (§13.4.3), pero no proporciona una razón. – Oded

+0

¿Qué ocurre si mi parámetro genérico en la subclase tiene restricciones contradictorias para el parámetro genérico en la clase base? – Paul

Respuesta

6

No puedo encontrar ninguna razón para que el C# no pueda copiar teóricamente las restricciones. Pero el comportamiento documentado de hacernos copiar (o aumentar) explícitamente parece ser la forma más sencilla de usabilidad.

public class A{} 
public class B : A {} 

public class X<T> where T: A {} 
public class Y<T> : X<T> where T: B { } 

En lo anterior, tenga en cuenta que yo no tenía que explicty copiar sobre la restricción en Y<T>, porque un B es siempre un A.

Ahora veamos qué sucede si el "compilador copia automáticamente las restricciones". Digamos que defino Y<T> sin restricciones y el compilador las coloca automáticamente. Yo uso Y<T> en muchos códigos. Luego modifico las restricciones en la declaración de X<T> para incluir alguna nueva interfaz.

Los errores de compilación para cambiar la declaración de X<T> se encuentran en los sitios donde yo utilizo Y<T>!

Con la forma en que funciona actualmente el compilador de C#, los errores del compilador están en los usos de X<T>, como era de esperar si lo cambio de manera abrupta.

Por lo tanto, si bien sería conveniente en algunos escenarios, también sería algo confuso en otros. Si bien ambos son enfoques válidos, asumiría (nótese que no puedo leer las mentes del equipo de diseño de C#) que fue una decisión y no puramente técnica.

Digo "no puramente técnico", pero ciertamente puedo imaginar algunos escenarios de interfaz donde sería más simple verificar que se cumplan todas las restricciones, en lugar de producir la restricción más simple que cumpla con todas las restricciones heredadas requeridas.

5

Conocimiento del equipo estándar C#. Las declaraciones deben ser autodocumentadas. Y, sobre todo, un cambio en una declaración de tipo no debe alterar el comportamiento de otro tipo sin relación, sin generar un diagnóstico. El principio de -100 puntos puesto en el diseño es otra visión de eso.

1

Las limitaciones en la interfaz son demasiado vagas para indicar al compilador las restricciones que debe tener la clase Module. Por ejemplo, la clase Module podría tener una restricción en una superclase (clase heredada) de DataBean.

No conozco la sabiduría de los diseñadores de C#. Debido a que las restricciones pueden ser diferentes, creo que se tomó la decisión de que el desarrollador declare explícitamente la restricción en lugar de hacer que el compilador haga suposiciones.

Cuestiones relacionadas