How to Implement an Interface Without Making Members Public Using Explicit Interface Implementation


If you’ve ever implemented an interface, you’ve probably encountered the requirement that the member you are implementing must be public.  For example, you cannot define a property in an interface and then make the setter internal as demonstrated by the following example:


image


If you attempt to compile the above code, you will receive an error stating that the class does not implement the interface member because it’s not public.


image


There are use cases for implementing interfaces and make the members non-public.  Building off the example above, suppose I want all entity objects to have a an Id property that anyone can get, but only internal classes can set


I’ll walk you through a series of code revisions and solve the problem using explicit interface implementation.  Explicit implementation essentially hides the class member so that it can only be accessed through the interface.  To use this feature, prefix the member you are implementing with the interface name, as demonstrated by the Id property below:


image


Now the Id property is no longer visible from the Customer class: 


image


To access an explicitly implemented member, cast it to the interface that contains the member (IEntity in this example):


image


I don’t want my consumers to have to cast entity objects to IEntity every time they need to access the Id property, so I’ll add a read-only Id property on the class.  At first it might feel strange having a member with the same name without using overloading, overriding or hiding (new keyword), but it actually is pretty logical.  A class can implement many interfaces, and explicit implementation is the mechanism that handles name clashes when two interfaces define a member with the same name.


image 


Although it may appear we have arrived at the solution, we aren’t quite there yet.  Explicit implementation hides the member, but it does not restrict access to it; consumers can still cast the object and access the member.  To restrict access, we will split non-public members into an interface, and put an appropriate access modifier on the interface.  This way consumers cannot cast to that interface and access explicitly implemented members, because they can’t access the interface.  Let’s revisit the example and make some changes.  First, the public interface should only contain that which is public, so we’ll remove the setter.


image


Now we’ll move the Id property setter into a new interface that is only visible internally:


image


Next, we’ll update the Customer entity to explicitly implement the IEntityIdSetter interface:


image


For illustrative purposes and to demonstrate why we used interfaces in the first place, we’ll also implement an Employee class that implements the same interfaces:


image


Now any class within the assembly can set the Id property and the interface enables us to operate on different types yet treat them as one.  In this example, we don’t care if it’s an Employee or a Customer, just that it supports setting the Id:


image


If any class outside the assembly attempts to set the property, the compiler will display an error that the property is read only:


image


 


Summary


Sometimes you need to implement an interface and don’t want a member to be public.  To achieve this, perform the following steps:



  • Separate non-public members into an interface

  • Set the interface access modifier to internal (you can’t use private, protected or protected internal)

  • Explicitly implement the non-public interface member(s)

 


References


Comments (5)

  1. Joe Enos says:

    Very nicely done.  Seems like a useful technique.

  2. Anders Borum says:

    While it’s a great example of explicit interface implementation, there’s a better solution with far less code. What you’re trying to express through the use of

    an interface is the get accessor to the "Id" field, while at the same time provide an internal set accessor in the concrete implementation.

    public interface IEntity

    {

       int? Id { get; }

    }

    public class Customer : IEntity

    {

      public int? Id { get; internal set; }

      // .. other class members here

    }

    Note the use of the automatic properties feature and the addition of the internal set accessor. It’s perfectly valid to add a set accessor (with the desired

    access modifier), even though it’s not expressed in the interface contract.

  3. Joe Enos says:

    Anders: Your sample is practically identical to the first code in the article, except the setter is removed from the interface.  I think the author’s technique is important because it shows that the setter can still be included in an interface, so you can use that style of programming, without exposing your setter to the outside or forcing internal code to reference the concrete class.

    Also, I do agree that auto-properties are the way to go for this scenario, but that really wasn’t the point of the article – and the code can be more easily followed by people who haven’t been exposed to the 3.x compilers.

  4. susL says:

    Anders, there’s a subtle but important difference in your solution and the author’s one.

    Using your code it’s impossible to SET Id through interface. Suppose you also have Employee class that implements IEntity. Using your solution one can’t write the NullId function presented in the article.

  5. tsahi says:

    That's the best solution to the problem I've found so far!