#536 – Using a Generic Interface

Like classes, interfaces can be generic.  Below is an example of a generic interface with  a single type parameter.

    public interface IRememberMostRecent<T>
    {
        void Remember(T thingToRemember);
        T TellMeMostRecent();
        List<T> PastThings { get; }
    }

When a class implements this interface, it can choose to fully construct the interface (provide a type).

    public class Farmer : IRememberMostRecent<Joke>
    {
        public string Name { get; protected set;  }

        public Farmer(string name)
        {
            Name = name;
            lastJoke = null;
            allJokes = new List<Joke>();
        }

        // IRememberMostRecent implementation
        private Joke lastJoke;
        private List<Joke> allJokes;

        public void Remember(Joke jokeToRemember)
        {
            if (lastJoke != null)
                allJokes.Add(lastJoke);

            lastJoke = jokeToRemember;
        }

        public Joke TellMeMostRecent()
        {
            return lastJoke;
        }

        public List<Joke> PastThings
        {
            get { return allJokes; }
        }
    }

Using the Farmer class:

            Farmer burton = new Farmer("Burton");
            burton.Remember(new Joke("A man walks into a bar.", "Ouch"));
            burton.TellMeMostRecent().Output();

            burton.Remember(new Joke("What's red and invisible?", "No tomatoes"));
            burton.TellMeMostRecent().Output();

#456 – Explicitly Implemented Interface Members Are Automatically Private

When you explicitly implement an interface member in a class, you make the member accessible only through objects whose type is the interface and not through objects whose type is the class.

    public class Cow : IMoo
    {
        void IMoo.Moo()
        {
            Console.WriteLine(string.Format("{0} says Moo", Name));
        }

        // rest of class here
            Cow bessie = new Cow("Bessie", 5);

            // bessie.Moo();    // Compile-time error

            IMoo viaMoo = bessie;
            viaMoo.Moo();       // OK

Because explicitly implemented interface members are not accessible via normal class instances, all explicitly implemented members are implicitly private.  These members cannot include an access modifier (either private or public).

#455 – Define an Interface Based on Existing Members of a Class

You can use Visual Studio to define a new interface, based on existing members of a class.  This is also known as extracting an interface.

For example, suppose we have an existing Cow class that doesn’t currently implement any interfaces.  A Cow has properties like Name, MooLog and Motto, and methods like Moo, Dance and Burp.

We can create a new IMoo interface that consists of a Moo method and a MooLog property.  Since Cow already implements both of these members, we can extract the interface from the class.

Right-click on the Cow class name and select Refactor and then Extract Interface.

We then give the new interface a name (e.g. IMoo) and select the members of the existing class that should be part of the interface.

After clicking OK, Visual Studio generates the new interface.

Cow now inherits from IMoo.

#454 – Return an Interface as a Return Value from a Method

In addition to passing interface variables into a method as parameters, you can also pass an interface back as the return value of a method.

In the example below, we define a method that looks through an array of objects and returns the first object found that implements the IMoo interface.

        static IMoo FindAMooer(object[] candidates)
        {
            IMoo theMooer = null;

            foreach (object candidate in candidates)
            {
                if (candidate is IMoo)
                {
                    theMooer = (IMoo)candidate;
                    break;    // stop looking
                }
            }

            return theMooer;
        }

We can then pass in any array of objects to this method and the method will find the first one that can moo.

            Cow bessie = new Cow("Bessie", 4);
            Dog spike = new Dog("Spike", 5);

            IMoo mooer = FindAMooer(new object[] { spike, 42, "Jude", bessie });
            mooer.Moo();

#452 – Object Browser Shows You the Interfaces that a Class Implements

In Visual Studio, you can see which interfaces a particular class implements by using the Object Browser.

Open the Object Browser window by selecting Object Browser under the View menu.

Once the Object Browser appears, you can navigate to the class that you want information on.  In the example below, we can see that the Cow class derives from Object and implements both IMoo and IStrangeCowBehavior.

We can’t tell from this view, however, which interfaces are implemented explicitly, i.e. requiring an interface-typed variable to access the methods.

You can click on the class itself to see all of the members of the class, including public and private members.

You can see all members.  Members in implicitly implemented interfaces (e.g. IMoo) show up as public members.  Members of explicitly implemented interfaces (e.g. IStrangeCowBehavior) show up as private.

You can also click on the interfaces to see members of each interface.

#451 – Implement Interface Explicitly to Simplify How a Class Appears to Clients

When you implement an interface explicitly, clients of the class can only see members of the interface if they access the object through the interface.

Assume that you have a Cow class which implements both the IMoo and the IStrangeCowBehavior interfaces.

public class Cow : IMoo, IStrangeCowBehavior

Also assume that the Cow class implements IStrangeCowBehavior explicitly, but implements IMoo normally.  Now a variable of type Cow will have access to the IMoo methods, but not the IStrangeCowBehavior methods.

If client code wants access to the IStrangeCowBehavior methods in Cow, it will need to access them via a variable of type IStrangeCowBehavior.

We’ve simplified things because most code that works with Cow objects won’t need access to the Burp, Dance, and DriveTractor methods and won’t even see the methods.  But code that needs these methods can get at them by using the appropriate interface variable.

#450 – Interfaces Should Normally Start with the Letter ‘I’

Interface names will typically start with the letter I, to help distinguish them from classes.

    interface IMoo
    {
        void Moo();
    }

Starting the name of an interface with the letter I is only an agreed-upon convention.  The name of the interface could actually be any valid type name.  But starting the interface name with the letter I helps readers of your code realize that the type is an interface type, rather than a class.

#449 – You Can Pass an Interface Variable to a Method

You can include a parameter in a method whose type is an interface, allowing you to pass interface variables into the method.

For example, we can write a method that takes variable of type IMoo.

        private static void DoSomeMooing(IMoo mooer)
        {
            for (int i = 0; i < 3; i++)
                mooer.Moo();
        }

We can now pass into this method a reference to any object that implements IMoo.

We might pass in an interface variable:

            Cow bessie = new Cow("Bessie", 4);
            IMoo viaMoo = bessie;
            DoSomeMooing(viaMoo);


We could also just pass an instance of a Cow directly into the method.  It will be implicitly cast to a reference of type IMoo and so the DoSomeMooing method will have access only to the members of Cow that are part of IMoo.

            Cow bessie = new Cow("Bessie", 4);

            DoSomeMooing(bessie);

#448 – Use the is Operator to See if an Object Implements an Interface

We saw that we could use the as operator to cast an object to a variable of a particular interface type.  If the object’s type does not implement the interface, the as operator returns null.

            IMoo viaMoo = objSomething as IMoo;
            if (viaMoo != null)
                viaMoo.Moo();

You can also use the is operator to first check to see if an object’s class implements a particular interface.

        private static void MooIfYouCan(object mooCandidate)
        {
            IMoo viaMoo;
            if (mooCandidate is IMoo)
            {
                viaMoo = (IMoo)mooCandidate;
                viaMoo.Moo();
            }
        }

We can pass any object into this method and the IMoo.Moo method will be called only if the object implements the IMoo interface.

            Cow bossie = new Cow("Bossie", 12);
            object mooer = bossie;
            MooIfYouCan(mooer);

            mooer = new Dog("Bert", 5);
            MooIfYouCan(mooer);

#447 – Use as Operator to Get At an Object’s Interfaces

If a class implements an interface, you can assign a variable whose type is that class directly to a variable of the interface’s type.

            Cow bossie = new Cow("Bossie", 12);

            IMoo viaMoo = bossie;
            viaMoo.Moo();

However, there might be times when you have a variable of a more general type and the variable may or may not implement a particular interface. In these cases, you could use a dynamic cast to cast the object variable to the interface type.

            object objSomething = bossie;

            // Can't assign directly; need cast
            IMoo viaMoo = (IMoo)objSomething;
            viaMoo.Moo();

The only problem is that this cast will fail, throwing an InvalidCastException, if the object does not implement IMoo.  Instead, you can use the as operator, which essentially does the cast, but just returns null if the cast fails.

            IMoo viaMoo = objSomething as IMoo;
            if (viaMoo != null)
                viaMoo.Moo();