Search code examples
c#.net-4.5ilistcontravariance

Returning a generic IList causing an error


I have the following structure:

public class MyBaseClass : IGeneralClass
{
}

public class MyClass : MyBaseClass 
{
    ...
}

public class MyDataClass
{
    private List<MyClass> _data = null;  

    public void PopulateData()
    {
        ...
    }

    public IList<IGeneralClass> Data
    {
        get 
        {
            return (IList<IGeneralClass>)_data;
        }
    }

}

I was under the impression that I could do this in .Net4.5 because of contravariance, but when I try, I get a runtime error as follows:

Unable to cast object of type 'System.Collections.Generic.List`1[MyClass]' to type 'System.Collections.Generic.IList`1[IGeneralClass]'.

Am I casting this incorrectly, or is this not supported?


Solution

  • I was under the impression that I could do this in .Net4.5 because of contravariance,

    You mean covariance, contravariance is the other way around, when A is a subtype of B, therefore X<B> is a subtype of X<A> (as is the case of Action<in T>).

    IList<T> is invariant though - notice how there's no in or out modifiers. You may be mistaking it for IEnumerable<out T>, which is covariant.

    Why is it invariant, I hear you ask? An IList<Dog> cannot be treated as an IList<Animal>, otherwise this would have to cause a runtime error:

    var listAnimals = listDogs as IList<Animal>();
    listAnimals.Add(cat);