CodeGym /Courses /C# SELF /Default Interface Methods

Default Interface Methods

C# SELF
Level 24 , Lesson 0
Available

1. From "pure contract" to flexible architecture

Before C# 8, an interface was like a strict contract: if you wanted to implement an interface, you had to implement everything, down to the last comma. If new members appeared, all existing implementations had to urgently add them, or else the compiler wouldn't let you build the project.

But life is messier. Imagine you're maintaining a library used by hundreds of projects, and suddenly you need to add a new method to an interface. Don't want to break backward compatibility? That's where default methods (Default Interface Methods, DIM) come in!

What's the deal?

Default methods let you declare a method implementation right in the interface. Now the contract is more flexible: if a class doesn't implement the "new thing," the default implementation will be used. It's like a stunt double in a movie: if the actor doesn't want to jump off a bridge, the stuntman steps in.

2. Syntax of Default Interface Methods

How do you declare methods with implementation in an interface?

It's a lot like regular methods, except now you can (and should) write the method body right in the interface:


public interface ILogger
{
    void Log(string message);

    // New method with a default implementation!
    void LogWarning(string message)
    {
        Log("[WARNING] " + message);
    }
}

Here, LogWarning already has an implementation! Any class that implements ILogger only has to implement Log, and LogWarning will get the default implementation (unless it has its own).

Compare: classic vs. modern signature

Version Declaration in interface
Before C# 8
void DoSomething();
C# 8 and newer
void DoSomething() { Console.WriteLine("Working!"); }

Important syntax details

  • For a method with an implementation, you must write the method body in curly braces.
  • Default methods can't be abstract.
  • All interface methods are still implicitly public.
  • You can also declare properties with default get/set (see below).

3. Practical examples

Example 1. Keeping backward compatibility

Let's say your app has an interface for saving data:


public interface ISaveable
{
    void Save(string filePath);
}

Later, you decide to add cloud saving. Don't want to change a hundred classes? Just add a default method!


public interface ISaveable
{
    void Save(string filePath);

    // New method with a "default" implementation!
    void SaveToCloud(string cloudService)
    {
        Console.WriteLine($"Saving to cloud {cloudService} (by default — does nothing)");
    }
}

Now all the old classes automatically "know how" to save to the cloud (even if for now it just prints a message).

Example 2. Expanding the logger interface

Earlier, we had a simple logging interface:


public interface ILogger
{
    void Log(string message);
}

Let's add a default method for logging errors:


public interface ILogger
{
    void Log(string message);

    void LogError(string message)
    {
        Log("[ERROR] " + message);
    }
}

A class implementing ILogger doesn't have to implement LogError — the default version will work:


public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
    // Not implementing LogError — default implementation will be used!
}

ILogger logger = new ConsoleLogger();
logger.Log("Everything's fine!");
logger.LogError("Uh-oh, something went wrong!"); // Calls the default implementation

Example 3. Default methods + extensible app

Your app supports different export types: to file, to DB, to network. The interface:


public interface IExporter
{
    void Export(string data, string destination);

    // New feature — export to archive
    void ExportToArchive(string data, string archivePath)
    {
        Console.WriteLine("Archiving is not supported by default.");
    }
}

Plugins written by other devs will keep working, even if they know nothing about the new method.

4. How does calling default interface methods work?

Scenario: "old class — new interface"

If a class doesn't implement a default interface method, when you call it through an interface reference, the interface implementation is used. If it does implement it — its own version is used.


public class FileExporter : IExporter
{
    public void Export(string data, string destination)
    {
        Console.WriteLine("Saving to file...");
    }
    // Not implementing ExportToArchive — default output will be used
}

IExporter exporter = new FileExporter();
exporter.Export("data", "file.txt");        // FileExporter's implementation runs
exporter.ExportToArchive("data", "file.zip"); // Default implementation runs!

Scenario: "class overrides default method"


public class AdvancedExporter : IExporter
{
    public void Export(string data, string destination)
    {
        Console.WriteLine("Saving in advanced mode...");
    }

    public void ExportToArchive(string data, string archivePath)
    {
        Console.WriteLine("Archiving is supported!");
    }
}

IExporter exporter = new AdvancedExporter();
exporter.ExportToArchive("data", "file.zip"); // Now the class implementation is called!

5. What else can you do with Default Interface Methods?

Default properties and events

You can declare properties with a default implementation, if they have a get or set body:


public interface IHasId
{
    // Automatically returns 42, unless overridden
    int Id => 42;
}

public class Person : IHasId {}
Console.WriteLine(new Person().Id); // 42

Calling default methods from interface code

Inside an interface, default methods and other interface members can call each other:


public interface IDemo
{
    void Foo() => Bar();
    void Bar() => Console.WriteLine("BAR");
}

6. Limitations and quirks of Default Interface Methods

Can you declare fields, constructors?

Nope. Even with default methods, an interface is still not a class. No fields, constructors, or destructors allowed.

Can you use base with interfaces?

You can, but with caveats. Inside a default interface method, you can call a parent interface method by specifying it explicitly:


public interface IBase
{
    void Greet() => Console.WriteLine("Hello from IBase");
}

public interface IDerived : IBase
{
    void IBase.Greet()
    {
        Console.WriteLine("Hello from IDerived!");
        IBase.Greet(this); // Explicitly call the base interface method
    }
}

But you rarely need this for basic scenarios.

What happens if default implementations conflict?


public interface IA { void Foo() { Console.WriteLine("A"); } }
public interface IB { void Foo() { Console.WriteLine("B"); } }

// Class doesn't explicitly implement Foo:
public class C : IA, IB { }
// Compile error: not clear which implementation to pick!

7. Typical mistakes, limitations, and quirks

Funny common mistake:
Some folks try to declare fields in an interface after learning about DIM — but you still can't have fields. Also, if you try to implement a static default method — before C# 8 that's impossible. (From version 8, you can have static methods in interfaces, but default implementations of static methods are a separate topic.)

Quirk: Diamond Problem
If your class implements two interfaces with the same default method, you have to explicitly implement that method:


public class ConflictClass : IA, IB
{
    public void Foo() // you have to pick which one!
    {
        // Explicitly call the needed implementation via interface (if needed)
        ((IA)this).Foo();
        // or
        ((IB)this).Foo();
    }
}

Don't overdo it!
Default methods save backward compatibility, but if you overuse them, you can end up with a "messy" architecture where some logic is scattered across interfaces. Try to keep all the important stuff in classes, and use interfaces as a real "contract."

2
Task
C# SELF, level 24, lesson 0
Locked
Extending an interface with a default method
Extending an interface with a default method
2
Task
C# SELF, level 24, lesson 0
Locked
Interface Conflict and Choosing an Implementation
Interface Conflict and Choosing an Implementation
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION