Explicit Interface Implementation — Resolving Conflicts and Hiding Members

Explicit interface implementation lets a class implement two interfaces that have members with identical names, without conflict. It is also used to hide implementation details — a member implemented explicitly is only accessible when the object is referenced through the interface type, not through the class type directly. This prevents callers from accidentally calling low-level implementation members when they have a class reference, while still satisfying the interface contract.

Resolving Name Conflicts with Explicit Implementation

public interface IReader
{
    string Read();   // returns a string
}

public interface IWriter
{
    void Write(string value);
}

// No conflict here — different signatures. But what if both had:
public interface IJsonSerializer
{
    string Serialize(object obj);
}

public interface IXmlSerializer
{
    string Serialize(object obj);   // same name AND signature!
}

// ── Explicit implementation resolves the conflict ─────────────────────────
public class DataSerializer : IJsonSerializer, IXmlSerializer
{
    // Explicit implementation — InterfaceName.MemberName
    string IJsonSerializer.Serialize(object obj)
    {
        return System.Text.Json.JsonSerializer.Serialize(obj);
    }

    string IXmlSerializer.Serialize(object obj)
    {
        var serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
        using var sw = new StringWriter();
        serializer.Serialize(sw, obj);
        return sw.ToString();
    }
}

// ── Accessing explicit members — MUST use interface reference ─────────────
var ds = new DataSerializer();
// ds.Serialize(obj);   // ← compile error! Serialize not accessible on DataSerializer

IJsonSerializer jsonSerializer = ds;
string json = jsonSerializer.Serialize(new { Name = "Alice" });  // ✓ JSON version

IXmlSerializer xmlSerializer = ds;
string xml = xmlSerializer.Serialize(new { Name = "Alice" });   // ✓ XML version
Note: Explicit implementations do not have an access modifier — they are always effectively public through the interface and inaccessible directly on the class. You cannot write public string IJsonSerializer.Serialize(...) — the public is implied and adding it explicitly is a compile error. This makes the design intent clear: the member is part of a specific contract, not a general-purpose method of the class.
Tip: Use explicit implementation when you want to hide interface members from the class’s primary API. For example, a class might implement IDisposable explicitly so that callers using the class type directly do not see the Dispose() method (which is an implementation detail), while code that receives the object as IDisposable (like a using statement) can still call it. ASP.NET Core uses this pattern extensively in framework classes where the public API and the interface implementation are intentionally separated.
Warning: Explicit implementations can confuse developers who see the interface signature but cannot find the method when looking at the class in their IDE. If you override a member explicitly without a corresponding implicit version, consumers must know to cast to the interface to access it. Document this with XML comments: /// See <see cref="IJsonSerializer.Serialize"/> for the implementation. For most application code, implicit implementation (without the interface prefix) is simpler and preferred.

Hiding Implementation Details

// IDisposable implemented explicitly — Dispose() hidden on the class reference
public class DatabaseConnection : IDisposable
{
    private bool _disposed = false;

    public void Open()  => Console.WriteLine("Connection opened");
    public void Query() => Console.WriteLine("Executing query...");
    public void Close() => Console.WriteLine("Connection closed");

    // Explicit — not visible when using DatabaseConnection directly
    void IDisposable.Dispose()
    {
        if (!_disposed)
        {
            Close();
            _disposed = true;
        }
    }
}

// Using statement uses IDisposable.Dispose() automatically
using (var conn = new DatabaseConnection())
{
    conn.Open();
    conn.Query();
}   // ← Dispose() called here via IDisposable interface, even though it's explicit

// conn.Dispose()   // ← would be compile error if only explicitly implemented

Common Mistakes

Mistake 1 — Trying to access explicit member on class reference

❌ Wrong — compile error:

var ds = new DataSerializer();
ds.Serialize(obj);   // compile error — must cast to interface first

✅ Correct — cast to the interface:

string json = ((IJsonSerializer)ds).Serialize(obj);
// or: IJsonSerializer js = ds; string json = js.Serialize(obj);

Mistake 2 — Adding access modifier to explicit implementation

❌ Wrong — compile error:

public string IJsonSerializer.Serialize(object obj) { }  // compile error!

✅ Correct — no access modifier on explicit implementations.

🧠 Test Yourself

Why is an explicitly implemented interface member only accessible through an interface reference and not through the class reference?