Trasmissione di un oggetto a un'interfaccia generica
Domanda
Ho la seguente interfaccia:
internal interface IRelativeTo<T> where T : IObject
{
T getRelativeTo();
void setRelativeTo(T relativeTo);
}
e un gruppo di classi che (dovrebbero) implementarlo, come:
public class AdminRateShift : IObject, IRelativeTo<AdminRateShift>
{
AdminRateShift getRelativeTo();
void setRelativeTo(AdminRateShift shift);
}
Mi rendo conto che questi tre non sono gli stessi:
IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>
ma ciò nonostante, ho bisogno di un modo per lavorare con tutte le diverse classi come AdminRateShift (e FXRateShift, DetRateShift) che dovrebbero implementare IRelativeTo. Diciamo che ho una funzione che restituisce AdminRateShift come un oggetto:
IRelativeTo<IObject> = getObjectThatImplementsRelativeTo(); // returns Object
Programmando contro l'interfaccia, posso fare quello che mi serve, ma non posso effettivamente lanciare l'Oggetto su IRelativeTo così posso usarlo.
È un esempio banale, ma spero che chiarirà ciò che sto cercando di fare.
Soluzione
Se capisco la domanda, l'approccio più comune sarebbe quello di dichiarare un'interfaccia di base non generica, ad esempio
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);
}
Un'altra opzione è quella di programmare in gran parte in generici ... cioè hai metodi come
void DoSomething<T>() where T : IObject
{
IRelativeTo<IObject> foo = // etc
}
Se IRelativeTo<T>
è un argomento su DoSomething()
, allora di solito non è necessario specificare l'argomento di tipo generico da soli - il compilatore lo inferirà - cioè
DoSomething(foo);
anziché
DoSomething<SomeType>(foo);
Ci sono vantaggi per entrambi gli approcci.
Altri suggerimenti
purtroppo l'eredità non funziona con i generici. Se la tua funzione prevede IRelativeTo, puoi anche rendere generica la funzione:
void MyFunction<T>(IRelativeTo<T> sth) where T : IObject
{}
Se ricordo bene, quando si utilizza la funzione sopra non è nemmeno necessario specificare il tipo, il compilatore dovrebbe capirlo in base all'argomento fornito.
Se vuoi mantenere un riferimento a uno di questi oggetti IRelativeTo all'interno di una classe o di un metodo (e non ti interessa cosa sia T), devi rendere di nuovo generica questa classe / metodo.
Sono d'accordo, è un po 'di dolore.
Se tutto ciò che ti interessa è che IRelativePer trattare con IObjects, non è necessario renderlo generico:
interface IRelativeTo
{
IObject getRelativeTo();
void setRelativeTo(IObject relativeTo)
}
Le classi di implementazione possono comunque essere generiche:
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 {}
Quindi puoi farlo:
IRelativeTo irt = new AdminRateShift();
IObject o = irt.getRelativeTo();
irt.setRelativeTo(o);