views:

352

answers:

2

Hi all

would this be possible? (I don't have vs. 2010, so I can't try it myself, 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>
{
}

If I get it right, you could use this to actually implement covariance and contravariance in the same interface.

+3  A: 

No, you can't. In your example IList<T> is invariant. IList<T> would require to declare in/out to be covariant/contravariant. It's not possible to do that just by inheriting some interface that is covariant.

Mehrdad Afshari
+4  A: 

Well, your question is slightly confusing because of the existing IList<T> type. However, the following does compile:

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

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

You can even change it to extend 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>
{
}

The indexer is tricky, because you'd want different types involved. You could do:

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

and then put the indexer into ISimpleList<T> instead of course...

That doesn't let you use ISimpleList<T> variantly though, because you've basically forced TInput=TOutput.

An alternative approach is to separate out the input from the output:

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

Then you could write:

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

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

and vice versa for IReadableList. In other words, you allow variance for each side individually, but you never get variance for the two sides together.

Jon Skeet
It certainly does compile but it wouldn't be co/contra-variant. `ISimpleList<string>` cannot be used as `ISimpleList<object>`.
Mehrdad Afshari
Thanks for trying
Icey
I'll update my answer to be more specific - sorry, still thinking all this through.
Jon Skeet