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.

È stato utile?

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top