SyntaxStudy
Sign Up
C# Defining and Implementing Interfaces
C# Beginner 1 min read

Defining and Implementing Interfaces

An interface defines a contract: a set of members (methods, properties, events, indexers) that implementing types must provide. Interfaces enable programming to abstractions — you write code against an interface type, and any conforming implementation can be plugged in at run time or test time. Since C# 8, interfaces may contain default method implementations. A class that does not override a default method inherits the interface's implementation. This allows interfaces to evolve over time without breaking existing implementors, similar to Java's default methods. A class or struct may implement multiple interfaces, providing the equivalent of multiple inheritance for behaviour. Interface names conventionally begin with `I` (e.g. `IDisposable`, `IEnumerable`). The built-in `IDisposable` pattern and `using` statement are fundamental to resource management in .NET.
Example
// Defining and implementing interfaces

public interface IShape
{
    double Area    { get; }
    double Perimeter { get; }
    string Describe() => $"{GetType().Name}: area={Area:F2}, perimeter={Perimeter:F2}";
}

public interface IResizable
{
    void Scale(double factor);
}

// Implementing multiple interfaces
public class Circle : IShape, IResizable
{
    public double Radius { get; private set; }
    public Circle(double radius) => Radius = radius;

    public double Area      => Math.PI * Radius * Radius;
    public double Perimeter => 2 * Math.PI * Radius;

    public void Scale(double factor) => Radius *= factor;
}

// Using the interface type (abstraction)
static void PrintShape(IShape shape) => Console.WriteLine(shape.Describe());

var c = new Circle(5);
PrintShape(c);  // uses default interface method

((IResizable)c).Scale(2);
PrintShape(c);  // radius is now 10

// IDisposable pattern — ensures cleanup of unmanaged resources
public class FileLogger : IDisposable
{
    private StreamWriter? _writer;
    public FileLogger(string path) => _writer = new StreamWriter(path, append: true);
    public void Log(string message) => _writer?.WriteLine($"{DateTime.UtcNow:O} {message}");

    public void Dispose()
    {
        _writer?.Flush();
        _writer?.Dispose();
        _writer = null;
    }
}

// 'using' statement calls Dispose automatically
using var logger = new FileLogger("app.log");
logger.Log("Application started");