Multiple Interface Implementation

Vaibhav • September 10, 2025

In the previous article, we explored best practices for designing inheritance hierarchies. Now we turn to a powerful feature of C# that complements inheritance and enables flexible, modular design: multiple interface implementation. Unlike classes, which support only single inheritance, interfaces can be implemented in multiples - allowing a class to adopt several behaviors or capabilities at once. This article will walk you through how multiple interfaces work, how to implement them correctly, how to resolve naming conflicts, and how to design clean, maintainable code using this technique.

Why multiple interfaces?

Interfaces define contracts - sets of methods and properties that a class agrees to implement. In C#, a class can implement any number of interfaces, which makes interfaces ideal for modeling capabilities that cut across unrelated types. For example, you might have a IPrintable interface for anything that can be printed, and a ISavable interface for anything that can be saved to disk. A class like Invoice might implement both.

interface IPrintable
{
    void Print();
}

interface ISavable
{
    void Save(string path);
}

class Invoice : IPrintable, ISavable
{
    public void Print()
    {
        Console.WriteLine("Printing invoice...");
    }

    public void Save(string path)
    {
        Console.WriteLine($"Saving invoice to {path}");
    }
}

This design allows Invoice to participate in both printing and saving workflows, without being tied to a specific base class. You can now treat it as either IPrintable or ISavable depending on context.

IPrintable printable = new Invoice();
printable.Print();

ISavable savable = new Invoice();
savable.Save("invoice.pdf");

This is interface-based polymorphism in action - the same object can be viewed through different lenses, each exposing a specific capability.

Designing interfaces for modular capabilities

When designing interfaces for multiple implementation, think in terms of capabilities rather than inheritance. Each interface should represent a distinct behavior or responsibility. For example, instead of creating a large IDocument interface with dozens of methods, break it into smaller interfaces like IReadable, IWritable, and IPrintable.

interface IReadable
{
    void Read();
}

interface IWritable
{
    void Write(string content);
}

class TextFile : IReadable, IWritable
{
    public void Read()
    {
        Console.WriteLine("Reading text file...");
    }

    public void Write(string content)
    {
        Console.WriteLine($"Writing to text file: {content}");
    }
}

This approach follows the Interface Segregation Principle - one of the SOLID design principles - which encourages small, focused interfaces that don’t force classes to implement methods they don’t need.

Resolving method name conflicts

If two interfaces define methods with the same signature, and a class implements both, you may run into naming conflicts. C# allows you to resolve this using explicit interface implementation. This technique lets you implement each method separately and control how it’s accessed.

interface IPrinter
{
    void Print();
}

interface IScanner
{
    void Print();
}

class MultiFunctionDevice : IPrinter, IScanner
{
    void IPrinter.Print()
    {
        Console.WriteLine("Printing document...");
    }

    void IScanner.Print()
    {
        Console.WriteLine("Scanning document...");
    }
}

Here, MultiFunctionDevice implements both IPrinter and IScanner, each with a Print() method. By using explicit implementation, the class avoids ambiguity and keeps the methods separate.

MultiFunctionDevice device = new MultiFunctionDevice();

((IPrinter)device).Print(); // Prints
((IScanner)device).Print(); // Scans

You must cast the object to the appropriate interface to access the correct method. This is useful when you want to hide interface methods from the public API of the class.

Explicit interface methods are not accessible via the class instance directly. They are only available through the interface reference.

Combining interfaces with inheritance

A class can inherit from a base class and implement multiple interfaces at the same time. This allows you to combine shared behavior with flexible capabilities.

class BaseLogger
{
    public void Log(string message)
    {
        Console.WriteLine($"Base log: {message}");
    }
}

interface INotifier
{
    void Notify(string message);
}

class EmailLogger : BaseLogger, INotifier
{
    public void Notify(string message)
    {
        Console.WriteLine($"Sending email: {message}");
    }
}

The EmailLogger class inherits logging behavior from BaseLogger and adds notification capability via INotifier. This pattern is common in real-world systems where classes need both shared behavior and flexible contracts.

Using interfaces in collections and APIs

Interfaces are especially useful in collections and APIs. You can define a method that accepts an interface type, and it will work with any object that implements that interface.

void Process(IPrintable item)
{
    item.Print();
}

This method can accept any IPrintable object - invoice, report, label - without knowing the exact type. This makes your code more reusable and decoupled.

Similarly, you can store multiple interface-implementing objects in a collection:

List<ISavable> items = new List<ISavable>
{
    new Invoice(),
    new Report()
};

foreach (ISavable item in items)
{
    item.Save("output.txt");
}

This pattern is common in plugin systems, UI frameworks, and data pipelines, where you want to process a variety of objects through a common interface.

Testing with multiple interfaces

Multiple interface implementation makes testing easier. You can create mock implementations of interfaces to simulate behavior without relying on real dependencies. This allows you to isolate logic and verify interactions.

class MockPrinter : IPrintable
{
    public List<string> Messages = new List<string>();

    public void Print()
    {
        Messages.Add("Print called");
    }
}

You can inject MockPrinter into your code and verify that printing occurred, without actually printing anything. This technique is widely used in unit testing and test-driven development.

Design tips for multiple interfaces

When designing classes that implement multiple interfaces, keep the following tips in mind:

First, keep interfaces small and focused. Each interface should represent a single capability. This makes them easier to implement and test. Second, avoid overlapping method names unless you intend to use explicit implementation. Conflicting names can lead to confusion and bugs. Third, document your interfaces clearly. Describe what each method does, what inputs it expects, and what outputs it produces. This helps consumers understand how to use them correctly.

Prefer interfaces over base classes when modeling capabilities. Use multiple interfaces to compose behavior flexibly, and keep each interface focused on a single responsibility.

Summary

Multiple interface implementation is a powerful feature in C# that enables flexible, modular design. You’ve learned how to implement multiple interfaces in a single class, how to resolve naming conflicts with explicit implementation, how to combine interfaces with inheritance, and how to use interfaces in collections, APIs, and testing. By designing small, focused interfaces and composing them as needed, you can build systems that are extensible, testable, and easy to maintain.

In the next article, we’ll explore Interface Segregation - how to design interfaces that are client-specific and avoid forcing classes to implement unnecessary methods.