C# -

Default Interface Methods

Default Interface Methods (DIM) in C# were introduced in C# 8.0. They allow interfaces to include method implementations. This tutorial will cover the basics of default interface methods, their usage, best practices, and more.


1. Introduction to Default Interface Methods

Default Interface Methods allow you to provide method implementations in interfaces. This helps avoid breaking existing implementations when new methods are added to an interface.


2. Basic Usage

Here's a basic example of an interface with a default method implementation:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IDefaultMethodExample
{
    void DefaultMethod()
    {
        Console.WriteLine("This is a default method in an interface.");
    }
}

public class ExampleClass : IDefaultMethodExample
{
}

class Program
{
    static void Main(string[] args)
    {
        IDefaultMethodExample example = new ExampleClass();
        example.DefaultMethod();
    }
}
        
    

3. Overriding Default Methods

Classes implementing the interface can override the default method. Here's an example:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IDefaultMethodExample
{
    void DefaultMethod()
    {
        Console.WriteLine("This is a default method in an interface.");
    }
}

public class ExampleClass : IDefaultMethodExample
{
    public void DefaultMethod()
    {
        Console.WriteLine("This is an overridden method in the class.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IDefaultMethodExample example = new ExampleClass();
        example.DefaultMethod();
    }
}
        
    

4. Calling Default Methods

You can call default interface methods from within other methods of the interface. Here's how:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IDefaultMethodExample
{
    void DefaultMethod()
    {
        Console.WriteLine("This is a default method in an interface.");
    }

    void CallDefaultMethod()
    {
        DefaultMethod();
    }
}

public class ExampleClass : IDefaultMethodExample
{
}

class Program
{
    static void Main(string[] args)
    {
        IDefaultMethodExample example = new ExampleClass();
        example.CallDefaultMethod();
    }
}
        
    

5. Multiple Interface Inheritance

Default interface methods allow for more complex inheritance scenarios. Here's an example with multiple interfaces:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IFirstInterface
{
    void DefaultMethod()
    {
        Console.WriteLine("Default method in the first interface.");
    }
}

public interface ISecondInterface
{
    void DefaultMethod()
    {
        Console.WriteLine("Default method in the second interface.");
    }
}

public class ExampleClass : IFirstInterface, ISecondInterface
{
    void IFirstInterface.DefaultMethod()
    {
        Console.WriteLine("Implemented default method from the first interface.");
    }

    void ISecondInterface.DefaultMethod()
    {
        Console.WriteLine("Implemented default method from the second interface.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFirstInterface first = new ExampleClass();
        first.DefaultMethod();

        ISecondInterface second = new ExampleClass();
        second.DefaultMethod();
    }
}
        
    

6. Using Default Methods for Backward Compatibility

Default interface methods can be used to add new functionality to interfaces without breaking existing implementations. Here's an example:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IOldInterface
{
    void ExistingMethod();
    
    void NewDefaultMethod()
    {
        Console.WriteLine("This is a new default method in the interface.");
    }
}

public class OldClass : IOldInterface
{
    public void ExistingMethod()
    {
        Console.WriteLine("Existing method in the class.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IOldInterface oldClass = new OldClass();
        oldClass.ExistingMethod();
        oldClass.NewDefaultMethod();
    }
}
        
    

7. Combining Default and Abstract Methods

Interfaces can have both default and abstract methods. Here's how you can combine them:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IMixedInterface
{
    void AbstractMethod();
    
    void DefaultMethod()
    {
        Console.WriteLine("This is a default method in the interface.");
    }
}

public class MixedClass : IMixedInterface
{
    public void AbstractMethod()
    {
        Console.WriteLine("Implemented abstract method in the class.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IMixedInterface mixedClass = new MixedClass();
        mixedClass.AbstractMethod();
        mixedClass.DefaultMethod();
    }
}
        
    

8. Limitations and Considerations

There are some limitations and considerations when using default interface methods. Here are some important points to keep in mind:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IExampleInterface
{
    void DefaultMethod()
    {
        Console.WriteLine("Default method in the interface.");
    }
}

public class ExampleClass : IExampleInterface
{
    // Cannot override non-virtual member in the interface
    // public override void DefaultMethod() { }
}

class Program
{
    static void Main(string[] args)
    {
        IExampleInterface example = new ExampleClass();
        example.DefaultMethod();
    }
}
        
    

9. Default Properties and Events

Default interface methods can also include properties and events. Here's an example:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface IPropertyExample
{
    int Property { get; set; }

    int DefaultProperty { get; set; }

    void SetDefaultProperty(int value)
    {
        DefaultProperty = value;
    }
}

public class PropertyClass : IPropertyExample
{
    public int Property { get; set; }
    public int DefaultProperty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        IPropertyExample example = new PropertyClass();
        example.SetDefaultProperty(42);
        Console.WriteLine($"Default Property Value: {example.DefaultProperty}");
    }
}
        
    

10. Practical Use Cases

Default interface methods can be used in various practical scenarios. Here are some examples:

        
            using System;

namespace DefaultInterfaceMethodsExamples;

public interface ILogger
{
    void Log(string message);

    void LogInfo(string message)
    {
        Log($"INFO: {message}");
    }

    void LogError(string message)
    {
        Log($"ERROR: {message}");
    }
}

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}

class Program
{
    static void Main(string[] args)
    {
        ILogger logger = new ConsoleLogger();
        logger.LogInfo("This is an info message.");
        logger.LogError("This is an error message.");
    }
}
        
    

11. Best Practices for Using Default Interface Methods

Here are some best practices to follow when using default interface methods:



12. Conclusion

Default interface methods in C# provide a powerful tool for adding new functionality to interfaces without breaking existing implementations. By following best practices and understanding their limitations, you can effectively use default interface methods to improve your code.