2009-08-11 15 views
6

sarebbe possibile? (Non ho rispetto al 2010, quindi non posso provare io stesso, mi dispiace)IList utilizza covarianza e controvarianza in C#, è possibile?

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 ho capito bene, si potrebbe usare questo per implementare effettivamente covarianza e controvarianza nella stessa interfaccia.

risposta

5

No, non è possibile. Nell'esempio IList<T> è invariato. IList<T> richiederebbe dichiarare in/out essere covariante/controverso. Non è possibile farlo solo ereditando qualche interfaccia che è covariante.

8

Bene, la tua domanda è leggermente confusa a causa del tipo esistente IList<T>. Tuttavia, il seguente fa di compilazione:

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

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

si può anche cambiare per estendere 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> 
{ 
} 

L'indicizzatore è difficile, perché si vorrebbe diversi tipi coinvolti. Si potrebbe fare:

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

e poi mettere l'indicizzatore in ISimpleList<T> invece ovviamente ...

che non consente di utilizzare ISimpleList<T> variantly però, perché hai praticamente costretti TInput = tOutput.

Un approccio alternativo è quello di separare l'ingresso dall'uscita:

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

Poi si può scrivere:

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

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

e viceversa per IReadableList. In altre parole, permetti la varianza per ogni lato individualmente, ma non ottieni mai la varianza per i due lati insieme.

+0

Compilare certamente, ma non sarebbe co/contro-variante. 'ISimpleList ' non può essere usato come 'ISimpleList '. –

+0

Grazie per aver provato –

+0

aggiornerò la mia risposta per essere più specifica - mi dispiace, continuo a pensare a tutto questo. –

0

Se un'implementazione di una proprietà di lettura-scrittura è stata considerata anche un'implementazione di una proprietà di sola lettura, è possibile aggiungere una forma utile di covarianza e controvarianza di lista mediante IList (di T) derivato da IReadableList (di Out T) e IAddableList (di In T). A condizione che tali interfacce includessero semplicemente membri che erano presenti in IList (Of T) prima che venissero definiti, il codice che implementava IList (Of T) implementava automaticamente quegli altri membri. Sfortunatamente, affinché IReadableList sia covariante, dovrebbe avere una proprietà di indicizzatore di sola lettura; l'implementazione della proprietà read-write in IList non può essere sostituita. Avere IList (Of T) ereditato da una IReadableList utilizzabile (Of Out T) romperebbe quindi tutte le implementazioni di IList (Of T).

Problemi correlati