Jeremy Davis
Jeremy Davis
Sitecore, C# and web development
Article printed from: https://blog.jermdavis.dev/posts/2025/quirk-explicit-interfaces

A quirk of explicit interfaces

I didn't realise you could do this...

Published 30 June 2025
C# .Net ~4 min. read

One of the fun things about defining objects and their APIs in C# is thinking about which bits you want your consumers to see, and which bits need to be there just for you, and consumers should avoid using. Most developers are aware of keywords like public / private and internal for achieving this, but Explicit Interfaces are another approach to this...

The basics url copied!

An interface is a way of expressing a contract you want classes to implement, but without giving any implementation. For example, a simple example might look like:

public interface IExample
{
    void Start();
    void Stop();
    int Status();
}

					

And a class can implement that contract:

public class ExampleClass : IExample
{
    public void Start()
    {
        // code
    }

    public void Stop()
    {
        // code
    }

    public int Status()
    {
        // code
    }
}

					

So your code can work with these methods directly on an object:

var obj = new ExampleClass();
obj.Start();
// do stuff
obj.Stop();

					

Or your can access them by their interface instead:

public void DoStuff(IExample ex)
{
    ex.Start();
    // do stuff
    ex.Stop();
}

					

Being explicit url copied!

C# also has the concept of Explicit Interfaces - which are documented as being used to disambiguate if you find yourself implementing two interfaces on the same object where they both specify a method with the same signature. If you want to have two implementations for this method on the same class you can have one public one and one explicit one - where you have to cast the object to the interface type to call it.

Sometimes, however, you need a class to implement an interface for the internals of your app, and you don't really want to confuse users with it by making the implementation of it visible. You can't use access modifier keywords for this - interface members declared in your classes only allow public. So (perhaps abusing the compiler a bit?) you can use Explicit Interfaces achieve this. Basically this means you declare these members with their interface name rather than an access modifier and they are only visible when you've cast your object to the interface itself. For example:

public class ExampleClass : IExample
{
    void IExample.Start()
    {
        // code
    }

    void IExample.Stop()
    {
        // code
    }

    int IExample.Status()
    {
        // code
    }
}

					

So now this code won't compile:

var obj = new ExampleClass();
obj.Start();
// do stuff
obj.Stop();

					

Because obj doesn't expose a public Start() or Stop() method any more.

But this still works:

public void DoStuff(IExample ex)
{
    ex.Start();
    // do stuff
    ex.Stop();
}

					

Because the IExample interface does expose them, even if they're not public on the object any more.

So consumers of your ExampleClass won't see these methods in autocomplete, unless that object is explicitly cast to the interface type.

An interesting wrinkle url copied!

What I'd not realised until recently, is that it works to have only parts of your interface implemented explicitly. Declaring this compiles and works:

public class ExampleClass : IExample
{
    public void Start()
    {
        // code
    }

    public void Stop()
    {
        // code
    }

    int IExample.Status()
    {
        // code
    }
}

					

You've met the requirements of the interface because all the methods have a declaration. But normal users of an ExampleClass object can't see the Status() method because it is not declared as public.

But is it actually a good idea? url copied!

That's a good question - I'm still thinking about that. It's certainly not using Explicit Interfaces in the documented manner.

But I did come up with a scenario where this appears useful - even if it is a bit obscure:

Say you have a variety of types of "entity" in your system that all have an Id which needs to be assigned in a controlled manner. And you need to have type-specific entity stores which manage this creation process, while hiding where the Ids came from. Broadly this sounds like a use case for generics?

So you might have some sort of base entity like:

public abstract class Entity
{
    public int Id { get; }
}

					

and a store that looks something like:

public class EntityStore<T> where T : Entity, new()
{
    public T Fetch(int id)
    {
        // some code
    }

    public T New()
    {
       // some code
    }
}

					

Consumers of this code can derive something concrete from Entity and use an EntityStore to manage instances of them.

But how does the store set the Id on new entities in a way that stops consumers of these types changing it later? The two obvious answers would be "in the constructor" or "via the Id property" but neither of those seems great.

The property approach is pretty easy - just add a setter to the Id property. But making that setter invisible to normal consumers is tricky. Depending on the structure of your code you may not be able to use internal as that's not visible outside of the current DLL. And protected can't work because the store doesn't derive from the Entity type.

And sort of similarly, constructors are tricky. They're also difficult to hide, and you can only write constraints on the generic type T for a parameterless constructor. So you can't make a store which can only be used with entities that expose the right constructor. (Well - without factory methods - but that seems like a more complex approach)

But maybe that explicit interfaces idea does work here?

If we have an interface for "this object has a controlled Id" like so:

public interface IIdentifiable
{
    int Id { get; }
    void SetId(int id);
}

					

Then you can have an entity which uses a partial-explicit implementation:

public abstract class Entity, IIdentifiable
{
    private int _id = -1;

    public int Id => _id;

    IIdentifiable.SetId(int id)
    {
        _id = id;
    }
}

					

And the store can make use of knowing an Entity has to provide this interface:

public class EntityStore<T> where T : Entity, new()
{
    public T Fetch(int id)
    {
        // some code
    }

    public T New()
    {
       var id = SomeCodeToGenerateTheId();

       var e = new Entity();
       (e as IIdentifiable).SetId(id);

       return e;
    }
}

					

So now users can create new types derived from Entity and manage them using the generic store. But the autocomplete for their objects won't show them the SetId() method when they're working. This doesn't prevent consumer code casting an entity to the interface to get around this, but there's very little visibility protection that can't be defeated somehow - often via Reflection.

So it does look like it's an approach with some uses, even if they're not things you might use often...

↑ Back to top