Author avatar

Christian Findlay

Distinguishing the Explicit and Implicit Interface Implementation in C#

Christian Findlay

  • Sep 20, 2019
  • 8 Min read
  • 60 Views
  • Sep 20, 2019
  • 8 Min read
  • 60 Views
Languages
Frameworks
and Tools
C#

Introduction

C# interface members can be implemented explicitly or implicitly. In most cases, implementing a member implicitly is the least verbose and convenient choice. However, there are times when implicit implementations allow for ambiguity or create too many accessible members. Members can be implemented for an explicit interface to avoid ambiguous member access at the usage level. This article will discuss the difference between explicit and implicit implementations, and how explicit interface member implementations can solve the ambiguity.

Main Difference

The main difference between explicit and implicit implementations is that implicit implementations must expose access to the member on the implementing concrete type. This means that the member will be available on the concrete type. Explicit implementations of members do not allow access modifiers and will always have the default member access on the concrete type. In practice, this will always be private, so when the object is cast to the concrete type, the explicitly implemented members will not be accessible.

Implicit Implementation

Implicit implementations tend to be more common and more convenient for usage. They are less verbose and any usage of the concrete type will have the implementations of the members exposed. Implicit implementations don't include the name of the interface being implemented before the member name, so the compiler infers this. The members will be exposed as public and will be accessible when the object is cast as the concrete type.

Consider these interfaces:

1
2
3
4
5
6
7
8
9
public interface IGetsMessage1
{
    string GetMessage();
}

public interface IGetsMessage2
{
    string GetMessage();
}
csharp

The code below implements the members in an implicit way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ImplicitImplementationBase : IGetsMessage1
{
    public string GetMessage()
    {
        return nameof(IGetsMessage1);
    }
}

public class ImplicitImplementation : ImplicitImplementationBase, IGetsMessage2
{
    internal new string GetMessage()
    {
        return nameof(IGetsMessage2);
    }
}
csharp

Ambiguity

When calling GetMessage() on the concrete type ImplicitImplementation, it may not be clear which method will be called.

Consider this sample:

1
2
3
4
5
6
7
8
internal class Program
{
    private static void Main(string[] args)
    {
        var implicitImplementation = new ImplicitImplementation();
        Console.WriteLine(implicitImplementation.GetMessage());
    }
}
csharp

If ImplicitImplementation is defined in the assembly where Program is defined, the output will be "IGetsMessage2".Bbut if the type is moved to an external assembly, the public version of the method will be called and the result will be "IGetsMessage1". This is because GetMessage() in the class ImplicitImplementation has an internal access modifier. To solve this issue, the interface's members can be implemented explicitly.

Explicit Implementation

Explicit implementations of members require the interface name and a period before the member name, as below. The members will not be exposed by the concrete type but can be used when the object is cast to the interface. The word "explicit" refers to the explicit mention of the interface name, so it is clear which interface's member is being implemented. Also, It may be preferable to use explicit implementations to reduce the number of exposed members on a type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ExplicitImplementationBase : IGetsMessage1
{
    string IGetsMessage1.GetMessage()
    {
        return nameof(IGetsMessage1);
    }
}

public class ExplicitImplementation : ExplicitImplementationBase, IGetsMessage2
{
    string IGetsMessage2.GetMessage()
    {
        return nameof(IGetsMessage2);
    }
}
csharp

Consider this sample:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
internal class Program
{
    private static void Main(string[] args)
    {
        var implicitImplementation = new ImplicitImplementation();
        var getsMessage2 = (IGetsMessage2)implicitImplementation;
        Console.WriteLine(getsMessage2.GetMessage());

        var explicitImplementation = new ExplicitImplementation();
        getsMessage2 = explicitImplementation;
        Console.WriteLine(getsMessage2.GetMessage());

        Console.ReadLine();
    }
}
csharp

Output:

IGetsMessage1

IGetsMessage2

The explicitly implemented version calls the method that specifically belongs to IGetsMessage2 while the implicitly implemented version uses the first public version that it finds which is in ImplicitImplementationBase and not ImplicitImplementation. This is how explicit implementations can disambiguate member access.

The usage of ExplicitImplementation is different from ImplicitImplementation. The code below will not compile.

1
2
var explicitImplementation = new ExplicitImplementation();
Console.WriteLine(explicitImplementation.GetMessage());
csharp

The error message that will appear is:

'ExplicitImplementation' does not contain a definition for 'GetMessage' and no accessible extension method 'GetMessage' accepting a first argument of type 'ExplicitImplementation' could be found (are you missing a using directive or an assembly reference?)

This is because GetMessage() is declared with the default member access of private on the concrete type. To access the members, the object must be cast to the interface explicitly. This forces the user to disambiguate the members. Convenience and terseness are sacrificed for explicitness. It should be noted that most APIs tend toward implicit implementations for this reason. Explicit implementations can cause confusion. When confronted with the type, ExplicitImplementation, it is not possible to see which members are accessible on the type. Intelliprompt will not expose any members and it may not be clear how the class is meant to be used.

This code will produce the same results, but only the explicit version will force the usage to be explicitly unambiguous.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
internal class Program
{
    private static void Main(string[] args)
    {
        var explicitImplementation = new ExplicitImplementation();
        var test1 = (IGetsMessage1)explicitImplementation;
        var test2 = (IGetsMessage2)explicitImplementation;

        Console.WriteLine(test1.GetMessage());
        Console.WriteLine(test2.GetMessage());

        var implicitImplementation = new ImplicitImplementation();
        test1 = implicitImplementation as IGetsMessage1;
        test2 = implicitImplementation as IGetsMessage2;

        Console.WriteLine(test1.GetMessage());
        Console.WriteLine(test2.GetMessage());

        Console.ReadLine();
    }
}
csharp

Output

GetsMessage1

IGetsMessage2

IGetsMessage1

IGetsMessage2

Conclusion

To distinguish between an explicit and implicit interface implementation, check for the interface name before the implemented member declaration. Explicit implementations can disambiguate member access. The choice between explicit and implicit implementation changes the usage of the implementing class. This makes the choice a matter of coding style. It's important to understand the difference so that this can be discussed in your team and to understand how to use a concrete type where interface members are explicitly implemented. As always, consistency is key, and anyone consuming APIs should be given usage examples and explanations for how to use the types.

1