Skip to main content

Command Palette

Search for a command to run...

Mastering C# Part 7.3 Object Oriented Programming

Interface in depth

Updated
7 min read
Mastering C# Part 7.3 Object Oriented Programming
N

Hi, I'm Nishant Banjade, a Software Engineer at Ellucian, committed to transforming education through technology. With expertise in developing CRM systems, plugins, workflows, APIs, and customized solutions for Higher Education, I bring a strong focus on innovation and efficiency. Currently, I'm honing my skills in full-stack software development, system design, data structures, algorithms, and Microsoft Dynamics 365.

I am a skilled software developer with expertise in C#/.NET, D365, JavaScript, TypeScript, ReactJS, SQL, and cloud technologies like AWS, along with experience in RabbitMQ, Docker, MUI, Tailwind, JIRA, and Git.

Interfaces in C#

An interface in C# is a contract that defines a set of methods, properties, events, or indexers that a class or struct must implement. Unlike classes, interfaces do not provide any implementation for their members; they only declare them.


Key Features of Interfaces

  1. Declaration of Behavior:

    • Interfaces declare "what" a class must do, not "how" it does it.
  2. No Implementation:

    • An interface cannot contain fields, constructors, destructors, or implementation of methods.
  3. Multiple Inheritance:

    • A class can implement multiple interfaces, enabling multiple inheritance.
  4. Polymorphism:

    • Interfaces provide a way to achieve polymorphism by defining common behavior that can be implemented differently in multiple classes.
  5. Access Modifiers:

    • All members of an interface are implicitly public, and explicit access modifiers are not allowed.

Syntax

public interface IExample
{
    void Display();               // Method
    int Id { get; set; };         // Property
    event EventHandler OnChange;  // Event
    int this[int index] { get; set; }  // Indexer
}

Implementing an Interface

When a class implements an interface, it must provide concrete implementations for all interface members.

public class Example : IExample
{
    public int Id { get; set; }

    public event EventHandler OnChange;

    public int this[int index]
    {
        get { return index; }
        set { Console.WriteLine("Indexer set!"); }
    }

    public void Display()
    {
        Console.WriteLine("Interface method implemented.");
    }
}

Features in Depth

1. Multiple Interfaces

A class can implement multiple interfaces.

public interface IReadable
{
    void Read();
}

public interface IWritable
{
    void Write();
}

public class Document : IReadable, IWritable
{
    public void Read()
    {
        Console.WriteLine("Reading the document.");
    }

    public void Write()
    {
        Console.WriteLine("Writing the document.");
    }
}

2. Explicit Interface Implementation

If two interfaces have members with the same name, you can implement them explicitly to avoid ambiguity.

public interface IFirst
{
    void Display();
}

public interface ISecond
{
    void Display();
}

public class Example : IFirst, ISecond
{
    void IFirst.Display()
    {
        Console.WriteLine("First Interface Display");
    }

    void ISecond.Display()
    {
        Console.WriteLine("Second Interface Display");
    }
}

// Usage
var obj = new Example();
((IFirst)obj).Display();
((ISecond)obj).Display();

3. Interface Inheritance

Interfaces can inherit other interfaces.

public interface IBase
{
    void Show();
}

public interface IDerived : IBase
{
    void Display();
}

public class Example : IDerived
{
    public void Show()
    {
        Console.WriteLine("Show method from IBase.");
    }

    public void Display()
    {
        Console.WriteLine("Display method from IDerived.");
    }
}

4. Default Interface Methods (C# 8.0)

Starting with C# 8.0, interfaces can have default implementations for methods. However, these default methods cannot access private fields of the implementing class.

public interface IExample
{
    void MethodA();

    // Default method implementation
    void MethodB()
    {
        Console.WriteLine("Default implementation of MethodB.");
    }
}

public class Example : IExample
{
    public void MethodA()
    {
        Console.WriteLine("Implemented MethodA.");
    }
}

Common Use Cases

1. Dependency Injection

Interfaces are often used in dependency injection to decouple code and facilitate testing.

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

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

public class Application
{
    private readonly ILogger _logger;

    public Application(ILogger logger)
    {
        _logger = logger;
    }

    public void Run()
    {
        _logger.Log("Application is running.");
    }
}

2. Polymorphism

Interfaces allow classes to be treated uniformly, even if they implement behavior differently.

public interface IShape
{
    void Draw();
}

public class Circle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle.");
    }
}

public class Square : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a square.");
    }
}

class Program
{
    static void Main()
    {
        IShape[] shapes = { new Circle(), new Square() };

        foreach (IShape shape in shapes)
        {
            shape.Draw();
        }
    }
}

3. Marker Interfaces

A marker interface is an interface with no members, used to signify or "mark" a class for special behavior.

public interface IMarker { }

public class SpecialClass : IMarker { }

public class Program
{
    static void CheckMarker(object obj)
    {
        if (obj is IMarker)
            Console.WriteLine("This class is marked.");
    }
}

Interface vs Abstract Class

FeatureInterfaceAbstract Class
ImplementationCannot have implementation (except default methods).Can have implemented methods.
Multiple InheritanceA class can implement multiple interfaces.A class can inherit only one abstract class.
FieldsCannot have fields.Can have fields.
Access ModifiersAll members are public.Members can have any access modifier.
ConstructorsNot allowed.Can have constructors.

Key Points

  • Interfaces define a contract and promote design flexibility and extensibility.

  • Default methods in C# 8.0 allow providing a fallback implementation.

  • They are a cornerstone of polymorphism and abstraction in object-oriented programming.

  • Use interfaces to decouple implementations and make your code easier to maintain and test.

Difference Between Abstract Class and Interface

FeatureAbstract ClassInterface
PurposeUsed for shared behavior and implementation inheritance.Used for defining a contract that classes must adhere to.
ImplementationCan have both fully implemented methods and abstract methods.Cannot have method implementation (except default methods in C# 8.0+).
ConstructorsCan have constructors.Cannot have constructors.
FieldsCan have fields (variables).Cannot have fields.
PropertiesCan have properties with implementation.Can only have property declarations.
Access ModifiersMembers can have any access modifiers (e.g., public, protected, etc.).All members are implicitly public. Access modifiers are not allowed.
InheritanceA class can inherit only one abstract class.A class can implement multiple interfaces.
Use CaseUse when classes share common behavior and need some implemented code.Use when classes need to follow a common contract but have different implementations.
Default MethodsSupported (methods can have bodies).Supported in C# 8.0+ via default methods.
PerformanceSlightly faster due to compiled method calls.Slightly slower due to interface method dispatch.

When to Use Abstract Class vs Interface

  • Use Abstract Classes when:

    • You want to provide common functionality along with enforcing a contract.

    • You have shared fields or properties.

    • Classes are closely related.

  • Use Interfaces when:

    • You want to define a contract without dictating implementation.

    • You need to support multiple inheritances.

    • You want loose coupling between components.


Delegates vs Interfaces

FeatureDelegatesInterfaces
PurposeEncapsulates methods as objects and allows method references to be passed.Defines a contract for classes to implement specific behavior.
FunctionalityRepresents a single method or a group of methods.Represents a set of methods, properties, events, and indexers.
Use CaseUse for event handling or callback mechanisms.Use to enforce a structure or contract on implementing classes.
Multiple MethodsCan invoke multiple methods (multicast).Does not directly execute methods.
Multiple InheritanceNot applicable.Supports multiple inheritance.
FlexibilityMore flexible for scenarios where method invocation is required dynamically.Requires implementation by the class to adhere to the contract.
Event HandlingIdeal for event-driven programming.Not used for events directly.
Runtime BehaviorAllows runtime method assignment.Fixed implementation in the class.
ExampleTypically used for passing methods dynamically.Typically used to define behavior for a group of classes.

Examples

Delegate Example

// Delegate definition
public delegate void Notify(string message);

public class DelegateExample
{
    public static void NotifyViaEmail(string message)
    {
        Console.WriteLine($"Email Notification: {message}");
    }

    public static void NotifyViaSMS(string message)
    {
        Console.WriteLine($"SMS Notification: {message}");
    }

    public static void Main()
    {
        Notify notify = NotifyViaEmail;
        notify += NotifyViaSMS; // Multicast delegate

        notify("Your order is confirmed.");
    }
}

Output:

Email Notification: Your order is confirmed.
SMS Notification: Your order is confirmed.

Interface Example

public interface INotification
{
    void Notify(string message);
}

public class EmailNotification : INotification
{
    public void Notify(string message)
    {
        Console.WriteLine($"Email Notification: {message}");
    }
}

public class SMSNotification : INotification
{
    public void Notify(string message)
    {
        Console.WriteLine($"SMS Notification: {message}");
    }
}

public class InterfaceExample
{
    public static void Main()
    {
        INotification email = new EmailNotification();
        INotification sms = new SMSNotification();

        email.Notify("Your order is shipped.");
        sms.Notify("Your order is delivered.");
    }
}

Output:

Email Notification: Your order is shipped.
SMS Notification: Your order is delivered.

When to Use Delegates vs Interfaces

  • Use Delegates:

    • When you need to pass methods as parameters.

    • For event-driven programming (e.g., UI, logging systems).

    • For loosely coupled callback mechanisms.

  • Use Interfaces:

    • When you want to define a contract for multiple classes.

    • When you need polymorphism to use a common interface for different implementations.

    • For structured behavior with static binding.