Search code examples
c#.netgenericscovariancecontravariance

T must be contravariantly valid


What is wrong with this?

interface IRepository<out T> where T : IBusinessEntity
{
    IQueryable<T> GetAll();
    void Save(T t);
    void Delete(T t);
}

It says:

Invalid variance: The type parameter 'T' must be contravariantly valid on 'MyNamespace.IRepository.Delete(T)'. 'T' is covariant.


Solution

  • Consider what would happen if the compiler allowed that:

    interface IR<out T>
    {
        void D(T t);
    }
    
    class C : IR<Mammal>
    {
        public void D(Mammal m)
        {
            m.GrowHair();
        }
    }
    ...
    IR<Animal> x = new C(); 
    // legal because T is covariant and Mammal is convertible to Animal
    x.D(new Fish()); // legal because IR<Animal>.D takes an Animal
    

    And you just tried to grow hair on a fish.

    The "out" means "T is only used in output positions". You are using it in an input position.