Uses of Explicit Interface Implementation

   C# has a lot of features that are kind of obscure but are really cool when you need them. When I was young and reckless I once declared one particular C# feature stupid and useless. Less than a week later I had to use this feature to avoid writing some ugly code and realized how useful and deep the feature was. Since then I have learned not to question Anders's (Hallowed be His name!) wisdom even when I do not understand it. A few days ago I was astonished to find a new use for another feature that I thought I fully understood. According to the C# designers when they evaluate a feature they favor features that have multiple uses over features that solve only one problem. It seems like I underestimated the C# team once again and by now I should have known better. The feature in question is explicit interface implementation.

   Firstly, I will take a look at the obvious use of this feature just to make sure we are all on the same track. So I happen to have this School class that holds a list of students and a list of teachers. I also happen to have these two interfaces that I do no control or maybe I do control them but they are used in so many places that I cannot really change them. One of them is called IStudentCollection and the other is called ITeacherCollection. The School class should implement both these interfaces. Both of them have a Count property. While the implementation of this method is clear for both interfaces there is the problem with the names colliding. You cannot really write two different Count properties... unless you use explicit interface implementation.

   public interface IStudentCollection
   {
       int Count { get; }
   }

   public interface ITeacherCollection
   {
       int Count { get; }
   }

   public class School : IStudentCollection, ITeacherCollection
   {
       public List<Student> Students { get; set; }

       public List<Teacher> Teachers { get; set; }

       int IStudentCollection.Count
       {
           get { return Students.Count; }
       }

       int ITeacherCollection.Count
       {
           get { return Teachers.Count; }
       }
   }

And then the usage:

   School school = new School
                       {
                           Students = new List<Student> { new Student(), new Student() },
                           Teachers = new List<Teacher> { new Teacher() }
                       };

   var studentCollection = (IStudentCollection)school;
   //Outputs 2
   Console.WriteLine(studentCollection.Count);

   var teacherCollection = (ITeacherCollection)school;
   //Outputs 1
   Console.WriteLine(teacherCollection.Count);

As you can see this allows the School class to participate in polymorphic scenarios and the meaning of the Count property is determined by the compile time type of the variable used.

   All this is cool and useful but there is more to this feature than avoiding name collision. Consider the following code:

   Console.WriteLine(school.Count);

This will produce a compile time error. Despite the fact that the School class has two Count properties none of them can be used with a variable of type School. So what if I had this Lecture class that has a Teacher property and a list of students that it exposes as an IEnumerable but also exposes this StudentsCount property. As it happens it needs to implement IStudentCollection. Now we can easily implement a Count property that just returns StudentsCount but that would make the public interface of the Lecture class expose two properties that are essentially the same. Undoubtedly this is an ugly interface that you would not want to have in your classes. Luckily explicit interface implementation comes to the rescue.

   public class Lecture : IStudentCollection
   {
       public Lecture(List<Student> students, Teacher teacher)
       {
           Teacher = teacher;
           this.students = students;
       }

       public Teacher Teacher { get; private set; }

       private List<Student> students;
       public IEnumerable<Student> Students
       {
           get { return students; }
       }

       public int StudentsCount
       {
           get { return students.Count; }
       }

       int IStudentCollection.Count
       {
           get { return StudentsCount; }
       }
   }

...

   var studentCollection = (IStudentCollection)lecture;
   //Outputs 0 because this lecture is so boring that no one shows up
   Console.WriteLine(studentCollection.Count);


You can then use both the StudentsCount property as a public member of the Lecture class and the Count property when the variable is typed as a IStudentsCollection at compile time. The latter means that you can still use the Lecture class in polymorphic scenarios where IStudentCollection is expected. The Count property would not be allowed to compile from a variable typed as Lecture and will not pollute the public interface (including the intellisense) of Lecture and all its descendants. You can use this approach not only if there is duplicate functionality of methods like in this case but also when the a member of the interface just does not make sense for the public interface of the type. For example if the School class only needed to implement the IStudentsCollection interface we would not be faced with names collision but a property named Count would be useless and confusing on this class. What exactly do you count on a School? Is it the teachers or the students? In fact this was the problem I was faced with when I came up with the idea of using the explicit interface implementation. For a moment I wondered if this feature was meant to be used in this way or I just invented an ugly hack. Then I reasoned that if name collision was the only reason for this feature to be introduced then Anders (Hallowed be His name!) would command us via his tablet with commandments (a.k.a. the C# compiler) to have a default implementation which shows up in the public interface of the class. Restricting useless ways to do things is absolutely His style. For example you are not allowed to write the public modifier in front of members of interface types because it is useless. In His infinite wisdom Anders (Hallowed be His name!) thought of this usage of the feature and provided us with a way to do something like a lightweight version of the Façade pattern that proved useful for my code and may one day prove useful in yours.
Tags:   english programming 
Posted by:   Stilgar
13:35 12.07.2010

Comments:



No comments yet.




Post as:



Post a comment: