Mastering C# Part 7.3 Object Oriented Programming
Interface in depth

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
Declaration of Behavior:
- Interfaces declare "what" a class must do, not "how" it does it.
No Implementation:
- An interface cannot contain fields, constructors, destructors, or implementation of methods.
Multiple Inheritance:
- A class can implement multiple interfaces, enabling multiple inheritance.
Polymorphism:
- Interfaces provide a way to achieve polymorphism by defining common behavior that can be implemented differently in multiple classes.
Access Modifiers:
- All members of an interface are implicitly
public, and explicit access modifiers are not allowed.
- All members of an interface are implicitly
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
| Feature | Interface | Abstract Class |
| Implementation | Cannot have implementation (except default methods). | Can have implemented methods. |
| Multiple Inheritance | A class can implement multiple interfaces. | A class can inherit only one abstract class. |
| Fields | Cannot have fields. | Can have fields. |
| Access Modifiers | All members are public. | Members can have any access modifier. |
| Constructors | Not 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
| Feature | Abstract Class | Interface |
| Purpose | Used for shared behavior and implementation inheritance. | Used for defining a contract that classes must adhere to. |
| Implementation | Can have both fully implemented methods and abstract methods. | Cannot have method implementation (except default methods in C# 8.0+). |
| Constructors | Can have constructors. | Cannot have constructors. |
| Fields | Can have fields (variables). | Cannot have fields. |
| Properties | Can have properties with implementation. | Can only have property declarations. |
| Access Modifiers | Members can have any access modifiers (e.g., public, protected, etc.). | All members are implicitly public. Access modifiers are not allowed. |
| Inheritance | A class can inherit only one abstract class. | A class can implement multiple interfaces. |
| Use Case | Use when classes share common behavior and need some implemented code. | Use when classes need to follow a common contract but have different implementations. |
| Default Methods | Supported (methods can have bodies). | Supported in C# 8.0+ via default methods. |
| Performance | Slightly 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
| Feature | Delegates | Interfaces |
| Purpose | Encapsulates methods as objects and allows method references to be passed. | Defines a contract for classes to implement specific behavior. |
| Functionality | Represents a single method or a group of methods. | Represents a set of methods, properties, events, and indexers. |
| Use Case | Use for event handling or callback mechanisms. | Use to enforce a structure or contract on implementing classes. |
| Multiple Methods | Can invoke multiple methods (multicast). | Does not directly execute methods. |
| Multiple Inheritance | Not applicable. | Supports multiple inheritance. |
| Flexibility | More flexible for scenarios where method invocation is required dynamically. | Requires implementation by the class to adhere to the contract. |
| Event Handling | Ideal for event-driven programming. | Not used for events directly. |
| Runtime Behavior | Allows runtime method assignment. | Fixed implementation in the class. |
| Example | Typically 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.