Pergunta

Eu tenho a seguinte interface:

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

e um monte de classes que (deve) implementá-lo, tais como:

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

Eu percebo que estes três não são os mesmos:

IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>

mas mesmo assim, eu preciso de uma maneira de trabalhar com todas as diferentes classes como AdminRateShift (e FXRateShift, DetRateShift) que todos devem implementar IRelativeTo. Digamos que eu tenho uma função que retorna AdminRateShift como um objeto:

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

Ao programar contra a interface, eu posso fazer o que eu preciso, mas eu realmente não pode converter o objeto para IRelativeTo para que eu possa usá-lo.

É um exemplo trivial, mas eu espero que irá esclarecer o que estou tentando fazer.

Foi útil?

Solução

Se eu entendi a pergunta, em seguida, a abordagem mais comum seria declarar uma base de interface não genérica, i.

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);
}

Outra opção é para você código em grande parte em genéricos ... ou seja, você tem métodos como

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

Se o IRelativeTo<T> é um argumento para DoSomething(), então normalmente você não precisa especificar o argumento de tipo genérico si mesmo - o compilador irá inferir-lo -. I

DoSomething(foo);

em vez de

DoSomething<SomeType>(foo);

Há benefícios para ambas as abordagens.

Outras dicas

Infelizmente herança não trabalhar com os genéricos. Se a sua função espera IRelativeTo, você pode fazer a função genérica assim:

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

Se bem me lembro, quando você usa a função acima, você não precisa mesmo de especificar o tipo, o compilador deve descobrir isso com base no argumento que você fornecer.

Se você quiser manter uma referência a um destes IRelativeTo objetos dentro de uma classe ou método (e você não se importa o que T é isso), você precisa para fazer esta classe / método genérico novamente.

Eu concordo, é um pouco de dor.

Se tudo o que importa é que IRelativeTo lida com IObjects então você não precisa fazê-lo genérico:

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

As classes execução ainda pode ser genérica, no entanto:

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 {}

Em seguida, você pode fazer isso:

  IRelativeTo irt = new AdminRateShift();
  IObject o = irt.getRelativeTo();
  irt.setRelativeTo(o);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top