Skip to main content

C# Explicit Implementation

When working with interfaces in C#, you'll occasionally encounter naming conflicts or need more control over interface implementation. C#'s explicit interface implementation provides a powerful solution to these problems. In this tutorial, we'll dive into this important concept and see how it helps you write better code.

What is Explicit Interface Implementation?

Explicit interface implementation is a C# technique that allows a class to implement interface members in a way that they can only be accessed through an interface reference. This differs from the standard (implicit) implementation where interface members are accessible directly through the implementing class.

Why use Explicit Implementation?

  1. Resolve naming conflicts when implementing multiple interfaces with same-named members
  2. Hide complex interface members from users of your class
  3. Implement multiple versions of a method depending on which interface is being used
  4. Maintain clean public API by keeping interface-specific functionality separate

Basic Syntax for Explicit Implementation

Here's how you explicitly implement an interface method:

csharp
// Interface definition
interface IMyInterface
{
void MyMethod();
}

// Implicit implementation
class ImplicitClass : IMyInterface
{
public void MyMethod() // accessible directly
{
Console.WriteLine("Implicit implementation");
}
}

// Explicit implementation
class ExplicitClass : IMyInterface
{
void IMyInterface.MyMethod() // only accessible through interface
{
Console.WriteLine("Explicit implementation");
}
}

Using Explicit Implementation

To call an explicitly implemented member, you need to cast the object to the interface type:

csharp
class Program
{
static void Main()
{
// Using implicit implementation
ImplicitClass implicit = new ImplicitClass();
implicit.MyMethod(); // Works fine

// Using explicit implementation
ExplicitClass explicit = new ExplicitClass();
// explicit.MyMethod(); // Error! Method not accessible

// Correct way to call explicit implementation:
IMyInterface interfaceRef = explicit;
interfaceRef.MyMethod(); // Works fine

// Or using direct cast:
((IMyInterface)explicit).MyMethod(); // Also works
}
}

Output:

Implicit implementation
Explicit implementation
Explicit implementation

Resolving Naming Conflicts

One of the most common reasons to use explicit implementation is to resolve naming conflicts when implementing multiple interfaces:

csharp
interface IDrawable
{
void Draw();
}

interface IPrintable
{
void Draw(); // Same name as in IDrawable
}

class Document : IDrawable, IPrintable
{
// Explicit implementations to resolve conflict
void IDrawable.Draw()
{
Console.WriteLine("Drawing for screen display");
}

void IPrintable.Draw()
{
Console.WriteLine("Drawing for printer");
}

// Optional: Public method that uses both implementations
public void DrawDocument(bool forPrinting)
{
if (forPrinting)
{
((IPrintable)this).Draw();
}
else
{
((IDrawable)this).Draw();
}
}
}

Usage example:

csharp
Document doc = new Document();
// doc.Draw(); // Error! Which Draw method should be called?

// Use interfaces to specify which implementation to use
IDrawable drawableDoc = doc;
drawableDoc.Draw(); // Calls IDrawable implementation

IPrintable printableDoc = doc;
printableDoc.Draw(); // Calls IPrintable implementation

// Or use the public method that handles both
doc.DrawDocument(forPrinting: false);
doc.DrawDocument(forPrinting: true);

Output:

Drawing for screen display
Drawing for printer
Drawing for screen display
Drawing for printer

Hiding Complex Interface Members

Sometimes you may want to implement an interface but keep some of its members hidden from general use:

csharp
interface IAdvancedOperations
{
void SimpleOperation();
void ComplexOperation();
}

class UserFriendlyClass : IAdvancedOperations
{
// Publicly available
public void SimpleOperation()
{
Console.WriteLine("Simple operation anyone can use");
}

// Hidden from public API, only available through interface
void IAdvancedOperations.ComplexOperation()
{
Console.WriteLine("Complex operation for advanced users only");
}

// Public wrapper with safeguards
public void SafeComplexOperation()
{
Console.WriteLine("Adding safety checks...");
((IAdvancedOperations)this).ComplexOperation();
Console.WriteLine("Safety checks complete.");
}
}

Usage example:

csharp
UserFriendlyClass user = new UserFriendlyClass();
user.SimpleOperation(); // Available directly
// user.ComplexOperation(); // Error! Not accessible

// Advanced usage through interface
IAdvancedOperations advanced = user;
advanced.ComplexOperation(); // Works

// Recommended usage
user.SafeComplexOperation();

Output:

Simple operation anyone can use
Complex operation for advanced users only
Adding safety checks...
Complex operation for advanced users only
Safety checks complete.

Explicit Implementation with Properties and Events

You can explicitly implement properties and events just like methods:

csharp
interface IDataContainer
{
string Data { get; set; }
event EventHandler DataChanged;
}

class DataStore : IDataContainer
{
private string _internalData;

// Explicit property implementation
string IDataContainer.Data
{
get { return _internalData; }
set
{
_internalData = value;
OnDataChanged();
}
}

// Explicit event implementation
event EventHandler IDataContainer.DataChanged;

protected virtual void OnDataChanged()
{
((IDataContainer)this).DataChanged?.Invoke(this, EventArgs.Empty);
}

// Public API uses different names
public string StoredData
{
get { return _internalData; }
set
{
_internalData = value;
OnDataChanged();
}
}
}

Real-World Example: Repository Pattern

Explicit interface implementation is often used in the repository pattern where different interfaces provide different views of functionality:

csharp
// Read-only repository interface
interface IReadOnlyRepository<T>
{
IEnumerable<T> GetAll();
T GetById(int id);
}

// Full repository interface
interface IRepository<T> : IReadOnlyRepository<T>
{
void Add(T entity);
void Update(T entity);
void Delete(int id);
}

// Repository implementation
class ProductRepository : IRepository<Product>
{
private List<Product> _products = new List<Product>();

// Implement IReadOnlyRepository explicitly to reserve these methods
// for read-only scenarios
IEnumerable<Product> IReadOnlyRepository<Product>.GetAll()
{
Console.WriteLine("Read-only access");
return _products.AsReadOnly();
}

Product IReadOnlyRepository<Product>.GetById(int id)
{
Console.WriteLine("Read-only access");
return _products.Find(p => p.Id == id);
}

// Implement IRepository methods normally with full access
public IEnumerable<Product> GetAll()
{
Console.WriteLine("Full access");
return _products;
}

public Product GetById(int id)
{
Console.WriteLine("Full access");
return _products.Find(p => p.Id == id);
}

public void Add(Product entity)
{
_products.Add(entity);
}

public void Update(Product entity)
{
// Update implementation
}

public void Delete(int id)
{
_products.RemoveAll(p => p.Id == id);
}
}

Using the repository:

csharp
// Product class
class Product
{
public int Id { get; set; }
public string Name { get; set; }
}

// Usage
ProductRepository repo = new ProductRepository();
repo.Add(new Product { Id = 1, Name = "Laptop" });

// Using full repository
var allProducts = repo.GetAll();

// Using read-only repository
IReadOnlyRepository<Product> readOnlyRepo = repo;
var safeProducts = readOnlyRepo.GetAll();

Output:

Full access
Read-only access

Best Practices for Explicit Implementation

  1. Use explicit implementation when necessary, not by default
  2. Document which interfaces a class implements explicitly
  3. Use explicit implementation to hide complexity, not to make code confusing
  4. Consider providing public wrappers for explicitly implemented members when appropriate
  5. Avoid casting to interfaces throughout your code; it's a sign your design might need improvement

Common Gotchas

  1. Access modifiers: Explicit implementation cannot include access modifiers (public, private, etc.)
  2. Static members: Interfaces cannot have static members, so this issue doesn't arise
  3. Debugging: Debugging explicitly implemented members can be trickier
  4. Virtual/override: Explicitly implemented members cannot be marked virtual or override

Summary

Explicit interface implementation in C# provides a powerful way to:

  • Resolve naming conflicts between interfaces
  • Keep your class's public API clean and focused
  • Implement interface members differently depending on which interface is used
  • Hide complex implementation details from regular users of your class

By mastering explicit implementation, you can create more flexible and maintainable code, especially when working with complex systems that use multiple interfaces.

Exercises

  1. Create a class that implements both IComparable<T> and IEquatable<T> using explicit implementation.
  2. Implement a Logger class that implements both IDisposable and a custom ILogger interface with explicit implementation.
  3. Create a collection class that implements both IEnumerable<T> and a custom interface with a method that has the same name as one in IEnumerable<T>.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)