Interfaces - Explicit Implementations


When a member of an interface is implemented, its name may be fully qualified with the interface name. This creates an explicit implementation of the component.

For example given the interface:

interface I
{
     void Method();
}

it is possible to define the following class.

class Implementation : I
{
     void I.Method()
     {
      ...
     }
}

When the member Method() is implemented, the full name, including interface name, is specified. The public access modifier is not used. The default access must be used when explicitly implementing an interface. The resultant explicit implementation is not available to code outside the class.

Private Implementations

The next program contains an interface I which defines two methods f and g. A class Implementation then implements I. When the implementation is made, the method g() is explicitly implemented. An explicit implementation must be called through an interface reference. A reference to the interface I is created and the method g() is called through that reference.

// Interface7 - Explicit Implementation

using System;

public interface I
{
    void f();
    void g();
}

class Implementation : I
{
    public void f()
    { Console.WriteLine("In method f"); }

    void I.g()
    { Console.WriteLine("In method g"); }
 }

class Program
{
    static void Main()
    {
        Implementation obj = new Implementation();

        obj.f();

        // obj.g();  // Error: g is not directly accessible

        I reference = obj;
        reference.g();
    }
}

Because g() is implemented explicitly it cannot be made public in the class Implementation. The ensures that its implementation is private. The means that it can only be invoked through a reference to interface I (as above).

Removing Ambiguity with Explicit Implementations

The next program shows how ambiguities can be removed using explicit implementations.

// Interface8 - Explicit Implementation - Removing Ambiguities

using System;

public interface IA
{
    void f();    
}

public interface IB
{
    void f();
}

class Implementation : IA, IB
{
    void IA.f()
    { Console.WriteLine("In method IA.f"); }

    void IB.f()
    { Console.WriteLine("In method IB.f"); }

    public void IA_f()
    {
        IA AObj = this;
        AObj.f();
    }

    public void IB_f()
    {
        IB BObj = this;
        BObj.f();
    }
}

class Program
{
    static void Main()
    {
        Implementation obj = new Implementation();

        obj.IA_f();
        obj.IB_f();
    }
}

Two interfaces IA and IB are defined. Both these interfaces contain a method called f(). The class Implementation implements both these interfaces. Given that f() is defined in both IA and IB, the only way to implement f() in both these interfaces is with an explicit implementation. However, the explicit implementation of these methods renders them inaccessible to outside code except through references to IA and IB. To make both methods visible, two more methods IA_f and IB_f are defined. These methods use references to the interfaces IA and IB to get at the specific version of the function to be called. Effectively, this removes the ambiguity while implementing both interfaces.