2008-10-21 12 views
22

tengo la siguiente interfaz:casting un objeto a una interfaz genérica

internal interface IRelativeTo<T> where T : IObject 
{ 
    T getRelativeTo(); 
    void setRelativeTo(T relativeTo); 
} 

y un montón de clases que (debería) ponerla en práctica, tales como:

public class AdminRateShift : IObject, IRelativeTo<AdminRateShift> 
{ 
    AdminRateShift getRelativeTo(); 
    void setRelativeTo(AdminRateShift shift); 
} 

Soy consciente de que estos tres no son los mismos:

IRelativeTo<> 
IRelativeTo<AdminRateShift> 
IRelativeTo<IObject> 

pero sin embargo, necesito una manera de trabajar con todas las diferentes clases como AdminRateShift (y FXRat eShift, DetRateShift) que todos deberían implementar IRelativeTo. Digamos que tengo una función que devuelve AdminRateShift como un objeto:

IRelativeTo<IObject> = getObjectThatImplementsRelativeTo(); // returns Object 

Por la programación en contra de la interfaz, que puede hacer lo que necesito, pero en realidad no puedo enviar el objeto a IRelativeTo para que pueda usarlo .

Es un ejemplo trivial, pero espero que aclare lo que intento hacer.

Respuesta

22

Si entiendo la pregunta, entonces el método más común sería declarar una base de interfaz no genérico, es decir,

internal interface IRelativeTo 
{ 
    object getRelativeTo(); // or maybe something else non-generic 
    void setRelativeTo(object relativeTo); 
} 
internal interface IRelativeTo<T> : IRelativeTo 
    where T : IObject 
{ 
    new T getRelativeTo(); 
    new void setRelativeTo(T relativeTo); 
} 

Otra opción es para que usted pueda codificar en gran medida en los genéricos ... es decir, que tienen métodos como

void DoSomething<T>() where T : IObject 
{ 
    IRelativeTo<IObject> foo = // etc 
} 

Si el IRelativeTo<T> es un argumento a DoSomething(), a continuación, por lo general que no es necesario especificar el argumento de tipo genérico sí mismo - el compilador inferirá que - es decir,

DoSomething(foo); 

en lugar de

DoSomething<SomeType>(foo); 

Hay beneficios para ambos enfoques.

+4

Hola, hice el primer método que describió. ¿Hay alguna manera de hacer que una clase que hereda 'IRelativeTo ' no tenga que implementar 'IRelativeTo' también? –

+0

@dav_i si mantiene las dos interfaces, entonces no –

+0

Es una lástima, es de esperar que la palabra clave 'new' realmente lo oculte. Aunque supongo que si lanzas tu objeto a lo no genérico, no sabrías qué hacer ... ¡Gracias! –

11

desafortunadamente la herencia no funciona con genéricos. Si su función espera IRelativeTo, puede hacer que la función genérica, así:

void MyFunction<T>(IRelativeTo<T> sth) where T : IObject 
{} 

Si no recuerdo mal, cuando se utiliza la función de arriba que ni siquiera es necesario especificar el tipo, el compilador debe averiguarlo basado en el argumento que proporcionas

Si desea mantener una referencia a uno de estos objetos IRelativeTo dentro de una clase o método (y no le importa qué es T), debe volver a hacer esta clase/método genérico.

Estoy de acuerdo, es un poco doloroso.

5

Si todo lo que importa es que se ocupa de IRelativeTo IObjects entonces no es necesario para que sea genérica:

interface IRelativeTo 
{ 
    IObject getRelativeTo(); 
    void setRelativeTo(IObject relativeTo) 
} 

Las clases que implementan aún pueden ser genéricos, sin embargo:

abstract class RelativeTo<T> : IRelativeTo where T : IObject 
{ 
    public virtual T getRelativeTo() {return default(T);} 

    public virtual void setRelativeTo(T relativeTo) {} 

    IObject IRelativeTo.getRelativeTo() {return this.getRelativeTo(); } 

    void IRelativeTo.setRelativeTo(IObject relativeTo) 
    { this.setRelativeTo((T) relativeTo); 
    } 
} 

class AdminRateShift : RelativeTo<AdminRateShift>, IObject {} 

Luego puede hacer esto:

IRelativeTo irt = new AdminRateShift(); 
    IObject o = irt.getRelativeTo(); 
    irt.setRelativeTo(o); 
Cuestiones relacionadas