#1,069 – Contravariance and Generic Interfaces

Generic interfaces in C# are contravariant, provided that their type parameters are constrained with the in keyword.  A contravariant generic interface allows an assignment from a constructed version of the interface on a base class to a constructed version of the interface for a derived class.

For example, if BorderCollie derives from Dog and if IAddRemove<T> is contravariant, we can do the following:

            IAddRemove<Dog> dogAddRemove;
            // Assign dogAddRemove to some class that implements IAddRemove<Dog>
            IAddRemove<BorderCollie> bcAddRemove = dogAddRemove;

Below is a full example of defining a contravariant interface. Note that the LineOf<T> class implements both the covariant interface IFirstAndLast<T> and the contravariant interface IAddRemove<T>.

        public interface IFirstAndLast<out T>
        {
            T First();
            T Last();
        }

        public interface IAddRemove<in T>
        {
            void AddToEnd(T item);
            void RemoveFromFront(T item);
        }   

        public class LineOf<T> : IFirstAndLast<T>, IAddRemove<T>
        {
            private Queue<T> theQueue = new Queue<T>();

            public void AddToEnd(T d)
            {
                theQueue.Enqueue(d);
            }

            public void RemoveFromFront(T d)
            {
                theQueue.Dequeue();
            }

            public T First()
            {
                return theQueue.Peek();
            }

            public T Last()
            {
                return theQueue.Last();
            }
        }

        static void Main(string[] args)
        {
            LineOf<Dog> dogs = new LineOf<Dog>();

            IAddRemove<BorderCollie> bcAddRemove = dogs;
            bcAddRemove.AddToEnd(new BorderCollie("Kirby"));
            bcAddRemove.AddToEnd(new BorderCollie("Shep"));
        }

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

2 Responses to #1,069 – Contravariance and Generic Interfaces

  1. Jason says:

    Been looking for a simple explanation of this. Now I think “In=Assign Base to Derived”. Thanks for clearing that up.

  2. Steve says:

    Wow! That’s a good example to demonstrate how to use in or out in generic interface. Good to know it. Thanks.

Leave a comment