Pergunta

isso seria possível? (Eu não tenho vs. 2010, então eu não posso tentar isso sozinho, sorry)

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    public IEnumerator<TOutput> GetEnumerator();
    public void Add(TInput item);
}

public interface IList<T> : IComplexList<T, T>
{
}

Se eu entendi direito, você poderia usar isso para realmente implementar covariância e contravariance na mesma interface.

Foi útil?

Solução

Não, você não pode. No seu exemplo IList<T> é invariável. IList<T> exigiria a declarar in / out ser covariante / contravariant. Não é possível fazer isso apenas por herdar alguma interface que é covariante.

Outras dicas

Bem, sua pergunta é um pouco confuso por causa do tipo IList<T> existente. No entanto, o seguinte faz compilação:

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    IEnumerator<TOutput> GetEnumerator();
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

Você pode até mesmo alterá-lo para estender IEnumerable<TOutput>:

public interface IComplexList<out TOutput, in TInput>
    : IEnumerable<TOutput>
    where TOutput : TInput
{        
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

O indexador é complicado, porque você iria querer diferentes tipos envolvidos. Você poderia fazer:

TOutput Get(int index);
void Set(int index, TInput item);

e em seguida, colocar o indexador em ISimpleList<T> vez, é claro ...

Isso não permite que você use ISimpleList<T> variantly embora, porque você basicamente forçado TInput = TOutput.

Uma abordagem alternativa é a de separar a entrada da saída:

public interface IReadableList<out T> : IEnumerable<T>
{
    T Get(int index);
}

public interface IWritableList<in T>
{
    void Add(T item);
    void Set(int index, T item);
}

 public interface IMyList<T> : IReadableList<T>, IWritableList<T> {}

Em seguida, você poderia escrever:

public void Foo(IWritableList<string> x) { ... }

IMyList<object> objects = new MyList<object>();
Foo(objects);

e vice-versa para IReadableList. Em outras palavras, você permite que a variância para cada lado individualmente, mas você nunca terá variação para os dois lados juntos.

Se uma implementação de uma propriedade de leitura e escrita também foram consideradas uma implementação de uma propriedade somente leitura, pode-se adicionar uma forma útil de Lista covariância e contravariance por ter IList (do T) derivam de IReadableList (de Out T) e IAddableList (de No t). Desde que essas interfaces simplesmente incluiu membros que estavam presentes no IList (Of T) antes de serem definidos, código que implementou IList (Of T) seria implementar automaticamente os outros membros. Infelizmente, para IReadableList ser covariante, ele teria que ter uma propriedade do indexador só de leitura; a implementação da propriedade de leitura e escrita no IList não poderiam ser substituídos. Tendo IList (Of T) herdam de uma IReadableList utilizável (Of Out T) seria, assim, quebrar todas as implementações de IList (Of T).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top