Difference between Delegates and Interfaces in C#

Both interfaces and delegates are core ideas in C# that are essential to the planning and execution of object-oriented and event-driven programming. But they have different uses and fulfill different functions. In this article, you will learn about the difference between delegates and interfaces in C#. But before discussing their differences, you must know about the delegates and interfaces in C#.

Delegates:

  • A type called a delegate represents references to methods with a specific parameter list and return type. In C#, it functions essentially as a function pointer.
  • Usage: Events and callbacks are frequently implemented using delegates. By creating a contract for a method signature and then enabling the delegation of various methods to the delegate, they allow you to build extensible and flexible systems.
  • Flexibility: As long as the parameter lists and return types match the delegate's signature, delegates can represent methods with a variety of parameter lists and return types, giving them greater flexibility in terms of method signatures.
  • Event Handling: Several methods can be called when an event occurs by using delegates, which are frequently used in event handling scenarios.

Example:

// Delegate definition

public delegate void MyDelegate(string message);

// Usage of the delegate

public class MyClass

{

public void MyMethod(string message)

{

Console.WriteLine(message);

}

}

// Assigning method to delegate

MyDelegate myDelegate = new MyDelegate(new MyClass().MyMethod);

Interfaces:

  • A contract that outlines a collection of attributes and methods without offering any implementation is called an interface. All members defined by an interface must have concrete implementations provided by classes that implement it.
  • Usage: Classes can adhere to a common set of behaviors defined by interfaces, which help achieve abstraction. They offer a means of achieving several inheritances in C#.
  • Implementation: A class is able to inherit and expose the behaviors specified by multiple interfaces that it implements.
  • Interfaces facilitate polymorphism, which permits objects belonging to distinct classes to be regarded as instances of the same interface.

Example:

// Interface definition

public interface INMyInterface

{

void MyMethod(string message);

}

// Class implementing the interface

public class MyClass : INMyInterface

{

public void MyMethod(string message)

{

Console.WriteLine(message);

}

}

// Usage of the interface

IMyInterface myObject = new MyClass();

myObject.MyMethod("Hello, Interface!");

Differences between Delegates and Interfaces:

There are several differences between delegates and interfaces. Some main differences between delegates and interfaces are as follows:

AspectDelegatesInterfaces
PurposeManage groups of methods (such as callbacks and event handling) and pass methods as parameters.Define properties, events, and methods for contracts.
Method ChainingIt can chain multiple methods simultaneously.It is not supported
InheritanceIt does not supports inheritanceInheritance is supported.
Multiple BehaviorsIt does not support multiple behaviours.It can implement multiple behaviours and also struct.
TypeIt maintains method reference and defines method signature.Contract with declarations about the method, property, and event
Usage ScenarioHandling events and callbacks.Defining a group of associated attributes and methods that classes or structs must implement.
ExtensibilityExpandable using multicast delegates.It can grow through inheritance.
VarianceIt encourages both contra variance and covariance.It does not encourage variation.

When you need to control a collection of methods as an entity or pass a method as an argument, use a delegate (like in event handling). You can use an interface when defining a contract that classes or structs can implement.

C# CODE:

Let us take an example to illustrate the use of delegates and interface in C#.

using System;

// Delegate definition

public delegate void MyDelegate(string message);

// Interface definition

public interface IMyInterface

{

void MyMethod(string message);

}

// Class implementing the interface

public class MyClass : IMyInterface

{

// Implementation of the interface method

public void MyMethod(string message)

{

Console.WriteLine($"Class implementing interface: {message}");

}

// Additional method for delegate

public static void AdditionalMethod(string message)

{

Console.WriteLine($"Additional method: {message}");

}

}

class Program

{

static void Main()

{

// Using the delegate

MyDelegate myDelegate = new MyDelegate(MyClass.AdditionalMethod);

myDelegate += new MyClass().MyMethod; // Combining methods

// Invoking the delegate

myDelegate("Hello, Delegates!");

// Using the interface

IMyInterface myObject = new MyClass();

myObject.MyMethod("Hello, Interface!");

}

}

Output:

Additional method: Hello, Delegates!

Class implementing interface: Hello, Delegates!

Class implementing interface: Hello, Interface!

Example 2:

Let us take another example to illustrate the use of delegates and interface in C#.

using System;

// Delegate definition for an event

public delegate void EventHandler(string message);

// Interface definition

public interface ILoggable

{

void LogMessage(string message);

}

// Class implementing the interface and raising an event

public class Logger : ILoggable

{

// Event of type EventHandler

public event EventHandler LogEvent;

// Implementation of the interface method

public void LogMessage(string message)

{

Console.WriteLine($"Logging message: {message}");

// Raise the LogEvent

LogEvent?.Invoke($"Event: {message}");

}

}

class Program

{

static void Main()

{

// Create an instance of the Logger class

Logger logger = new Logger();

// Subscribe to the LogEvent using a delegate

EventHandler eventHandlerDelegate = (msg) => Console.WriteLine($"Delegate Handler: {msg}");

logger.LogEvent += eventHandlerDelegate;

// Subscribe to the LogEvent using a method

void MethodHandler(string msg)

{

Console.WriteLine($"Method Handler: {msg}");

}

logger.LogEvent += MethodHandler;

// Log a message, which triggers the event

logger.LogMessage("Hello, Logging!");

// Unsubscribe one of the handlers

logger.LogEvent -= eventHandlerDelegate;

// Log another message

logger.LogMessage("Logging after unsubscribing one handler");

}

}

Output:

Logging message: Hello, Logging!

Delegate Handler: Event: Hello, Logging!

Method Handler: Event: Hello, Logging!

Logging message: Logging after unsubscribing one handler

Method Handler: Event: Logging after unsubscribing one handler

Example 3:

Let us take an example to illustrate the use of delegates and interface in C#.

using System;

// Delegate definition

public delegate void Operation(int a, int b);

// Interface definition

public interface ICalculator

{

int Add(int a, int b);

int Subtract(int a, int b);

}

// Class implementing the interface

public class BasicCalculator : ICalculator

{

// Implementation of the interface methods

public int Add(int a, int b)

{

Console.WriteLine($"Adding: {a} + {b} = {a + b}");

return a + b;

}

public int Subtract(int a, int b)

{

Console.WriteLine($"Subtracting: {a} - {b} = {a - b}");

return a - b;

}

// Additional method for delegate

public static void Multiply(int a, int b)

{

Console.WriteLine($"Multiplying: {a} * {b} = {a * b}");

}

}

class Program

{

static void Main()

{

// Using the delegate

Operation operationDelegate = BasicCalculator.Multiply;

operationDelegate += new BasicCalculator().Add; // Combining methods

// Invoking the delegate

operationDelegate(5, 3);

// Using the interface

ICalculator calculator = new BasicCalculator();

int resultAdd = calculator.Add(8, 2);

int resultSubtract = calculator.Subtract(10, 4);

Console.WriteLine($"Result of Add: {resultAdd}");

Console.WriteLine($"Result of Subtract: {resultSubtract}");

}

}

Output:

Multiplying: 5 * 3 = 15

Adding: 8 + 2 = 10

Subtracting: 10 - 4 = 6

Result of Add: 10

Result of Subtract: 6

Example 4:

using System;

// Delegate definition for an event

public delegate void EventHandler(string message);

// Interface definition for an event handler

public interface IEventSubscriber

{

event EventHandler CustomEvent;

void RaiseEvent(string message);

}

// Class implementing the interface

public class EventPublisher : IEventSubscriber

{

// Event declaration based on the delegate

public event EventHandler CustomEvent;

// Implementation of the interface method

public void RaiseEvent(string message)

{

Console.WriteLine($"EventPublisher is raising an event: {message}");

// Trigger the event

CustomEvent?.Invoke(message);

}

}

// Class subscribing to the event

public class EventSubscriber

{

// Event handler method

public void HandleEvent(string message)

{

Console.WriteLine($"EventSubscriber received the event: {message}");

}

}

class Program

{

static void Main()

{

// Creating instances

EventPublisher publisher = new EventPublisher();

EventSubscriber subscriber = new EventSubscriber();

// Subscribing to the event

publisher.CustomEvent += subscriber.HandleEvent;

// Raising the event

publisher.RaiseEvent("Hello, Event!");

// Unsubscribing from the event (optional)

publisher.CustomEvent -= subscriber.HandleEvent;

}

}

Output:

EventPublisher is raising an event: Hello, Event!

EventSubscriber received the event: Hello, Event!

Example 5:

using System;

using System.Collections.Generic;

// Delegate definition for a log message

public delegate void LogHandler(string message);

// Interface definition for a logging service

public interface ILogger

{

event LogHandler OnLog;

void LogMessage(string message);

}

// Class implementing the interface

public class SimpleLogger : ILogger

{

// Event declaration based on the delegate

public event LogHandler OnLog;

// Implementation of the interface method

public void LogMessage(string message)

{

Console.WriteLine($"Logging: {message}");

// Trigger the event

OnLog?.Invoke(message);

}

}

// Class subscribing to the log event

public class LogSubscriber

{

// Event handler method

public void HandleLog(string message)

{

Console.WriteLine($"LogSubscriber received the log message: {message}");

}

}

class Program

{

static void Main()

{

// Creating instances

SimpleLogger logger = new SimpleLogger();

LogSubscriber subscriber = new LogSubscriber();

// Subscribing to the log event

logger.OnLog += subscriber.HandleLog;

// Logging a message

logger.LogMessage("Information: Application started.");

// Unsubscribing from the log event (optional)

logger.OnLog -= subscriber.HandleLog;

}

}

Output:

Logging: Information: Application started.

LogSubscriber received the log message: Information: Application started.

Example 6:

using System;

using System.Collections.Generic;

// Delegate definition for a notification

public delegate void NotificationHandler(string message);

// Interface definition for a notification service

public interface INotificationService

{

event NotificationHandler OnNotify;

void Notify(string message);

}

// Class implementing the interface

public class NotificationManager : INotificationService

{

// Event declaration based on the delegate

public event NotificationHandler OnNotify;

// Implementation of the interface method

public void Notify(string message)

{

Console.WriteLine($"Sending notification: {message}");

// Trigger the event

OnNotify?.Invoke(message);

}

}

// Class subscribing to the notification event

public class NotificationSubscriber

{

// Event handler method

public void HandleNotification(string message)

{

Console.WriteLine($"NotificationSubscriber received the notification: {message}");

}

}

class Program

{

static void Main()

{

// Creating instances

NotificationManager notificationManager = new NotificationManager();

NotificationSubscriber subscriber1 = new NotificationSubscriber();

NotificationSubscriber subscriber2 = new NotificationSubscriber();

// Subscribing to the notification event

notificationManager.OnNotify += subscriber1.HandleNotification;

notificationManager.OnNotify += subscriber2.HandleNotification;

// Notifying with a message

notificationManager.Notify("Important Update!");

// Unsubscribing from the notification event (optional)

notificationManager.OnNotify -= subscriber1.HandleNotification;

// Notifying again

notificationManager.Notify("Another Notification");

}

}

Output:

Sending notification: Important Update!

NotificationSubscriber received the notification: Important Update!

NotificationSubscriber received the notification: Important Update!

Sending notification: Another Notification

NotificationSubscriber received the notification: Another Notification

Conclusion:

Interfaces and delegates are two fundamental ideas in C# that have different uses in the context of object-oriented programming. You can use delegates to reference and invoke methods with particular signatures, which serve as function pointers. Since they enable method signature flexibility, they are especially helpful for implementing callback and event-driven scenarios. But interfaces specify a set of methods and properties and do not provide implementation details; instead, they define contracts that classes must follow. Software design can be organized and modularized due to interfaces, which encourage code abstraction, polymorphism, and multiple inheritances. Interfaces define shared behaviors and create a contract for implementing classes, whereas delegates are used mainly for method references and event handling.