Any chance to cast legally?

107 Views Asked by At

This is my very first time to post a question here, so thanks in advance to anyone will help me (and maybe others).

Today I've been puzzled with covariance and contravariance in C# 4, but I really can't see any possibility to do what I would. NOTE: all that is NOT to solve a specific problem, but I'd like to know if there's any legal way (brand-new co/contra-variance in C# 4) to solve it. So, don't get crazy...

Here the sample code:

public interface IBase<in T>
{
    T GetValue();
    ...
}


public class Readable<T> : IBase<T>
{
    public T GetValue() {/* */}
    ...
}


public class Writeable<T> : IBase<T>
{
    public T GetValue() {/* */}
    public void SetValue(T value) {/* */}
    ...
}


public class Program
{
    private List<IBase<object>> _collection = new List<IBase<object>>();


    public static void Main()
    {
        var p = new Program();

        p._collection.Add(new Readable<bool>());    //not allowed
    }
}

The collection should be able to host any of the IBase derivatives, being them of any T. Of course I may use a non-generic collection or a List and the game is over. Another idea is having a more common interface IBaseCore, then IBase inherits from. My question is: without these tricks may I achieve to have a collection of IBase and add items of any IBase?

Thanks to everyone.

1

There are 1 best solutions below

2
On BEST ANSWER

EDIT: First things first, your variance is wrong for IBase<T>. It should be out T (covariant) rather than in T (contravariant).

The problem here is simply that generic covariance and contravariance doesn't work with value types as the type arguments. So you could add a Readable<string>, but not a Readable<bool>.

One option is to have a nongeneric base interface:

public interface IBase
{
    object GetValueAsObject();
}

public interface IBase<out T> : IBase
{
    T GetValue();
    ...
}

Then you could have a List<IBase>.