Sobes.tech
Junior

In which cases and for what purposes do we use interfaces in C#?

sobes.tech AI

Answer from AI

Interfaces in C# are used for the following purposes:

  1. Defining a contract: An interface defines a set of members (methods, properties, events, indexers) that a class or struct implementing this interface must implement. This ensures uniformity in the behavior of different types.

    // Interface definition
    public interface IDrawable
    {
        void Draw();
        int LineThickness { get; set; }
    }
    
    // Class implementing the interface
    public class Circle : IDrawable
    {
        public int LineThickness { get; set; }
    
        public void Draw()
        {
            // Logic for drawing a circle
        }
    }
    
  2. Polymorphism: Using interfaces allows working with objects of different types through a common interface type. This is achieved because any reference to an object implementing an interface can be cast to that interface type.

    // Method working with any object implementing IDrawable
    public void Render(IDrawable item)
    {
        item.Draw(); // Calls the specific implementation of Draw
    }
    
    // Usage:
    IDrawable circle = new Circle();
    Render(circle); // Will call the Draw() implementation from the Circle class
    
  3. Multiple Inheritance: C# does not support multiple class inheritance, but allows a class or struct to implement multiple interfaces. This enables a type to have behaviors defined in different "contracts".

    public interface ISaveable
    {
        void Save();
    }
    
    public interface ILoadable
    {
        void Load();
    }
    
    // Class implementing multiple interfaces
    public class ConfigurationManager : ISaveable, ILoadable
    {
        public void Save()
        {
            // Save logic
        }
    
        public void Load()
        {
            // Load logic
        }
    }
    
  4. Loose Coupling: Using interfaces reduces dependencies between components. Instead of depending on a specific class, a component can depend on an interface. This facilitates replacing implementations and testing.

    public interface ILogger
    {
        void LogMessage(string message);
    }
    
    public class FileLogger : ILogger
    {
        public void LogMessage(string message)
        {
            // File writing logic
        }
    }
    
    public class DatabaseLogger : ILogger
    {
        public void LogMessage(string message)
        {
            // Database writing logic
        }
    }
    
    public class ProcessingEngine
    {
        private readonly ILogger _logger;
    
        // Dependency on interface, not on a specific implementation
        public ProcessingEngine(ILogger logger)
        {
            _logger = logger;
        }
    
        public void ProcessData()
        {
            // ...
            _logger.LogMessage("Data processed.");
        }
    }
    
  5. Extensibility: Interfaces make it easy to add new implementations of existing behaviors without changing the code that uses this interface.

  6. Documentation and self-documentation: A well-named interface with comments on its members serves as a form of documentation, describing what behavior is expected from objects implementing this interface.