#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"));
        }
Advertisements

#1,068 – Generic IEnumerable Interface Is Covariant

A covariant generic interface is one that allows an assignment from a constructed version of the interface on a derived class to a constructed version of the interface for a base class.

For example:

            // If herders is (or implements) IFirstAndLast<BorderCollie>:
            IFirstAndLast<Dog> dogLine = herders;

The IEnumerable<T> interface in System.Collections.Generic is covariant.  This means that you can assign a collection of a given type to an IEnumerable<T> where the represents a type further up the inheritance chain.

For example:

            List<BorderCollie> someBCs = new List<BorderCollie> {
                new BorderCollie("Shep"),
                new BorderCollie("Kirby")
            };

            // Because BorderCollie derives from Dog,
            // we can do the following
            IEnumerable<Dog> dogList = someBCs;

If MerleBorderCollie inherits from BorderCollie, which in turn inherits from Dog, we can also do:

            List<MerleBorderCollie> merles = new List<MerleBorderCollie>
            {
                new MerleBorderCollie("Lady")
            };
            IEnumerable<Dog> moredogs = merles;

#1,067 – Covariance and Generic Interfaces

Generic interfaces in C# are covariant, provided that their type parameters are constrained with the out keyword.

Let’s assume that we have the following interface.

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

Then assume that we define a generic class that implements this interface:

        public class LineOf<T> : IFirstAndLast<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();
            }
        }

Great, now we can use this class as follows:

            LineOf<Dog> dogs = new LineOf<Dog>();
            dogs.AddToEnd(new Dog("Lassie"));
            dogs.AddToEnd(new Dog("Rin Tin Tin"));
            Console.WriteLine(dogs.First().ToString() + ", " + dogs.Last().ToString());

            LineOf<BorderCollie> herders = new LineOf<BorderCollie>();
            herders.AddToEnd(new BorderCollie("Kirby"));
            herders.AddToEnd(new BorderCollie("Shep"));
            Console.WriteLine(herders.First().ToString() + ", " + herders.Last().ToString());

At this point, we might want to convert LineOf<BorderCollie> to IFirstAndLast<Dog>, for example we might have a method that returns IFirstAndLast<Dog>.

However, if we do the following, we get a compiler error, saying that we can’t implicitly cast LineOf<BorderCollie> to IFirstAndLast<Dog>:

            IFirstAndLast<Dog> dogLine = herders;

We could do a cast, as shown below. The code now compiles, but the conversion fails at runtime.

            IFirstAndLast<Dog> dogLine = (IFirstAndLast<Dog>)herders;

We want the IFirstAndLast<T> interface to be covariant, i.e. to allow this assignment.  To support this, we just need to add the out keyword in the interface.

        public interface IFirstAndLast<out T>

We can do this because T is only used in this interface as a return value.  Having done this, we can now do the following.  This compiles and the assignment succeeds at runtime.

            IFirstAndLast<Dog> dogLine = herders;

 

#800 – A Property in an Interface May Include One or Two Accessors

Defining a property in an interface, you can define one or both of the property’s accessors.

    public interface IDogInfo
    {
        int CollarSize { get; set; }
        string Name { get; }
        string SecretName { set; }
    }

When you implement an interface, if a property in the interface has both accessors, you must implement both accessors, and both must be public (you set an access modifier of public on the entire property).

If a property in the interface includes only one accessor, you must implement that accessor, but you can optionally also implement the other accessor.

    public class Dog : IDogInfo
    {
        public int CollarSize { get; set; }

        // IDogInfo has just get
        public string Name
        {
            get { return "NotImpl"; }
        }

        // IDogInfo has just set, but we add a get
        public string SecretName { protected get; set; }
    }

#799 – Interface Members Are Implicitly Public

When you declare an interface, you cannot use access modifiers on interface’s member.  An interface makes a collection of members available to code that accesses a class implementing that interface.  So it makes sense that the interface members are public.

    public interface IBark
    {
        int BarkCount { get; set; }
        void Bark(string woofSound, int count);
    }

When you implement an interface, you must mark the interface members as public.

    public class Dog : IBark
    {
        public int BarkCount { get; set; }

        public void Bark(string woofSound, int count)
        {
            for (int i = 1; i <= count; i++)
                Console.WriteLine(woofSound);
        }
    }

If you implement the interface explicitly, the members are implicitly public and you cannot mark them with access modifiers.

        int IBark.BarkCount { get; set; }

        void IBark.Bark(string woofSound, int count)
        {
            for (int i = 1; i <= count; i++)
                Console.WriteLine(woofSound);
        }

#647 – A struct Can Implement an Interface

You’ll most often see an interface implemented by a class, but a struct can also implement an interface.

struct implements an interface in the same way as a class–by listing the name of the interface after the name of the struct and then by providing implementations of the members in the interface.

Suppose that we had the following interface:

    public interface IBoxCalcs
    {
        double CalcVolume();
        double CalcSurfaceArea();
    }

We can then implement this interface in a struct.

    public struct BoxSize : IBoxCalcs
    {
        public double x;
        public double y;
        public double z;

        // Constructor that fully initializes the object
        public BoxSize(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public double CalcVolume()
        {
            return x * y * z;
        }

        public double CalcSurfaceArea()
        {
            return (2 * x * y) + (2 * x * z) + (2 * y * z);
        }
    }

#613 – Interfaces Cannot Contain Static Members

An interface is a list of methods, properties, events and indexers that a class may implement.  All methods, properties and events defined in the interface are implicitly instance members, rather than static members.

    public interface IDogStuff
    {
        bool CanBark { get; set; }
        void Bark();

        // Compile-time Error: The modifier 'static' is not valid for this item
        static string GenerateMotto();

    }