2010-06-15 22 views
13

Soy básicamente querer hacer esto:¿Cómo heredar de un parámetro genérico?

class UILockable<T> : T 
    where T : UIWidget 
{ 
} 

Sin embargo, esto no funciona. He visto gente recomienda que haga esto:

class UILockable<T> 
    where T : UIWidget 
{ 
    private T _base; 
} 

Esto me requeriría para anular cada función UILockable necesitaría y lo remitirá a T. Esto es imposible ya que T puede derivar de UIWidget y tienen Único/virtuales métodos propios.

¿No hay forma de simplemente heredar de T?

+0

Considere forzar el tipo genérico para implementar una interfaz específica. No puede saber qué tipo exacto es T, y si está buscando métodos específicos que cualquier T pueda o no tenga, no va a funcionar. Haga que todos esos objetos implementen ILockable que fuerza esos métodos, como un contrato. – drharris

+1

Si no necesita reemplazar los métodos protegidos para lograr su lógica de bloqueo, puede rediseñar esto utilizando un objeto de servicio de bloqueo que asocie instancias de UIWidget con objetos LockContext utilizados para su lógica de bloqueo. No creo que la herencia sea una buena forma conceptual para lo que estás tratando de hacer, ya que estás tratando de aumentar la funcionalidad en general, no expresar una relación concreta 'es-a'. –

+0

posible duplicado de [Herencia en un parámetro de tipo genérico restringido] (http://stackoverflow.com/questions/1420581/inheritance-on-a-constrained-generic-type-parameter) – joce

Respuesta

16

No puede heredar del parámetro de tipo genérico. Los genéricos C# son muy diferentes de las plantillas C++. Heredar del parámetro tipo requiere que la clase tenga una representación completamente diferente basada en el parámetro tipo, que no es lo que sucede con los genéricos .NET. Son idénticos en el nivel IL y nativo (para todos los argumentos de tipo de referencia).

3

No, no lo hay. Sin embargo, realmente no entiendo su argumento en contra de que UILockable<T> Heredar del UIWidget y desviar todas las llamadas en su T:

class UILockable<T> : UIWidget 
    where T : UIWidget 
{ 
    private readonly T t; 

    public void SomeMethod() 
    { 
     this.t.SomeMethod(); 
    } 
} 

Usted no se preocupan por los detalles de implementación de UIWidgetT 's - sólo que se es una implementación de UIWidget.

+3

Creo que lo que está diciendo es que si hazlo de esta forma, no se podrá acceder a ningún método de 'T' que no esté especificado por' UIWidget'. –

+1

En ese caso, necesitaría agregar restricciones más genéricas de manera que T amplíe UIWidget e implemente también algunas interfaces. –

3

Piénsalo de esta manera: Cuando Tipo B hereda de tipo A , estás declarando que B es similares a Un (donde similitud significa que se puede utilizar B donde quiera que espere usar A). Ahora debido a que tal similitud no es simétrico que tiene que B es similar a Un pero Un no es similar a B. Además, B y C pueden ambos ser similar a A (es decir, que ambos descienden de A) sin ser similares entre sí.

Entonces, ¿qué desea declarar es que desbloqueable es similar a todo lo que es similar a UIWidget, pero eso es imposible porque el tipo de similitud no es transitivo (es decir, si B es similar a Un y C es similar a A no se puede decir que B es similar a C).

+0

@Robert ¿Por qué esta no es la respuesta? – AgentFire

+1

@AgentFire: Porque pasa por alto el punto esencial: 'Desbloqueable ' sería similar a 'T', no a otras subclases de' UIWidget', y sería similar en virtud de heredar el comportamiento de 'T'. –

0

No puede heredar de un argumento de tipo genérico. C# es un lenguaje estrictamente tipado. Todos los tipos y la jerarquía de herencia se deben conocer en tiempo de compilación. Los genéricos de .Net son muy diferentes de las plantillas de C++.

Y cuando esté tan seguro de que el argumento tipo T va a ser de tipo UIWidget, ¿por qué no heredar de UIWidget? Si alguna vez se lo permite [asumiendo, suponiendo, sé que esto nunca será posible], ¿qué lograría al heredar su clase de T que ya es de tipo UIWidget? En el momento del diseño, solo codificará contra UIWidget, entonces, ¿por qué no heredar directamente desde UIWidget?

+0

¿Por qué no heredar directamente de 'UIWidget'? * Mixins *. El hecho de que mixin solo pueda usar la interfaz esencial proporcionada por 'UIWidget', no significa que al consumidor no le gustaría tener el comportamiento de mezcla y algún comportamiento de widgets más especializado * en el mismo objeto *. –

+0

Siendo fuertemente tipado estáticamente y prohibiendo esta herencia son completamente ortogonales. – Puppy

Cuestiones relacionadas