C# Generics – Covariance and Contravariance

  • Only interfaces and delegate type support out and in keywords.
  • Covariance uses the OUT keyword. It is read-only. The type T comes out of the interface as a return value.
  • If your interface type can be covariant, your design will be more flexible if you mark it as covariant (with the out modifier)
  • Contravariance means varying oppositely.
  • Contravariance applies to types that are being written or provided to methods in a generic interface as parameters.

Contravariance Example


// Contravariance 
interface IGobbler<in T> { 
    void gobble(T t); 
} 
public class QuadrupedGobbler: IGobbler<FourFootedAnimal> 
{ 
    public void gobble(FourFootedAnimal t){} 
} 
public class FourFootedAnimal {} 
public class Donkey: FourFootedAnimal {} 
public static class TestContravariance { 
    public static void Run() 
    { 
        // Since a QuadrupedGobbler can gobble any four-footed 
        // creature, it is OK to treat it as a donkey gobbler. 
        IGobbler<Donkey> dg = new QuadrupedGobbler(); 
        dg.gobble(new Donkey()); 
    } 
}

In the above code, the following statement is allowed by the compiler, because the Gobble method in QuadrupedGobbler

IGobbler<Donkey> dg = new QuadrupedGobbler();

would have made calls to members contained in FourFootedAnimal, which are nothing but a subset of members in Donkey. So, the following statement cannot result in a runtime exception due to a member not being found.

dg.gobble(new Donkey())

Covariance Example

// Covariance 
interface ISpewer<out T> { 
    T spew(); 
} 
public class MouseSpewer: ISpewer<Mouse> 
{ 
    public Mouse spew(){ return new Mouse(); } 
} 
public class Rodent{} 
public class Mouse : Rodent{} 
public static class TestCovariance { 
    public static void Run() 
    { 
        // A MouseSpewer obviously spews rodents (all mice are 
        // rodents), so we can treat it as a rodent spewer. 
        ISpewer<Rodent> rs = new MouseSpewer(); 
        Rodent r = rs.spew(); 
    } 
}

Leave a Comment

Your email address will not be published. Required fields are marked *