Mastering C# Interfaces: Your Ultimate Guide
Table of Contents
- What is interface
- Advantages of Using Interfaces
- Where to Use C# Interfaces
- Real-world Examples
- Types of Interfaces
- Multiple Interface Implementation
- Tricky Questions and Answers
- Conclusion
Introduction
In C#, an interface is a blueprint or contract that defines a set of method and property signatures that a class must implement. In simpler terms, an interface is like a promise that a class makes to provide certain functionality. It ensures that classes adhere to a specific structure, which promotes code consistency and allows for better organization and abstraction in object-oriented programming.
Interfaces in C# are crucial for achieving abstraction, and flexibility. They define a set of methods and properties that implementing classes must adhere to, enabling a clean separation of concerns in your code.
Advantages of Using Interfaces
C# interfaces offer several advantages
- Abstraction: Interfaces allow you to define a contract for classes that implement them. This contract specifies the methods and properties that must be implemented by any class that uses the interface. This abstraction helps in designing systems without getting into the details of each implementation.
- Flexibility: Interfaces provide flexibility in the sense that a class can implement multiple interfaces. This allows you to mix and match different sets of functionality in your classes, making it easier to adapt to changing requirements.
Let’s say you have a Vehicle
class, and you want to add features like “CanFly” and “CanSwim” to various vehicles. By using interfaces, you can create two interfaces, IFlyable
and ISwimmable
, each defining the methods related to flying and swimming, respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
interface IFlyable { void Fly(); } interface ISwimmable { void Swim(); } class Vehicle : IFlyable, ISwimmable { public void Fly() { Console.WriteLine("This vehicle can fly."); } public void Swim() { Console.WriteLine("This vehicle can swim."); } } class Program { static void Main(string[] args) { Vehicle car = new Vehicle(); car.Fly(); // Output: This vehicle can fly. car.Swim(); // Output: This vehicle can swim. } } |
In this example, the Vehicle
class implements both IFlyable
and ISwimmable
interfaces, allowing it to have both flying and swimming capabilities. This flexibility makes it easy to adapt the Vehicle
class to changing requirements without altering its core functionality.
- Polymorphism: Interfaces facilitate polymorphism, which means that objects of different classes that implement the same interface can be treated uniformly. This simplifies code, making it more readable and extensible.
here’s an example that illustrates polymorphism using interfaces in C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using System; // Define an interface interface IShape { void Draw(); } // Concrete classes that implement the interface class Circle : IShape { public void Draw() { Console.WriteLine("Drawing a circle."); } } class Square : IShape { public void Draw() { Console.WriteLine("Drawing a square."); } } class Program { static void Main(string[] args) { // Create an array of IShape objects IShape[] shapes = new IShape[] { new Circle(), new Square() }; // Iterate through the array and call the Draw method on each object foreach (IShape shape in shapes) { shape.Draw(); // Polymorphism - different objects, same interface, uniform treatment } } } |
- Separation of Concerns: Interfaces enable a clean separation of concerns in your codebase, aligning with the Single Responsibility Principle (SRP) of the SOLID principles. By defining specific interfaces for different aspects of functionality, you ensure that each class adheres to a well-defined responsibility, promoting a modular and maintainable code structure.
- Testing and Mocking: Interfaces make it easier to test and mock components of your software. You can create mock objects that implement the same interface as the real objects, allowing you to isolate and test specific parts of your code.
- Interoperability: Interfaces are important for ensuring interoperability between different parts of a software system, especially in larger projects or when working with third-party libraries and frameworks. Interfaces provide a common language that different components can use to communicate.
- Reduced Coupling: When classes depend on interfaces rather than concrete implementations, it reduces the coupling between classes. This makes the codebase more maintainable and less prone to breaking when changes are made to individual classes.(The Dependency Inversion Principle, using Dependency Injection)
- Documentation: Interfaces serve as documentation for how classes should be used. They provide a clear contract that developers can follow when implementing or using classes, which can reduce misunderstandings and bugs in the code.
- Enforcement of Design Patterns: Interfaces can enforce design patterns, ensuring that classes adhere to a specific architectural style or pattern. For example, the Repository pattern can be enforced through interfaces that define data access methods, Factory pattern, Dependency Injection, in these all we can use Interfaces.
Rules & Steps creating Interface
When writing an interface in C#, you should follow certain rules and conventions to ensure clarity and maintainability in your code. Here are the key rules for writing interfaces in C#:
- Use the
interface
Keyword: Start your interface declaration with theinterface
keyword followed by the name of the interface. Interfaces are typically named using a capital ‘I’ as a prefix, followed by a descriptive name (e.g.,IShape
,ILogger
).interface IShape { // Interface members go here }
- Declare Members: Inside the interface, declare the methods, properties, events, or indexers that implementing classes must provide. Members declared in interfaces are implicitly
public
and should not have any access modifiers.interface IShape { void Draw(); // Method declaration string Name { get; set; } // Property declaration event EventHandler Clicked; // Event declaration }
- No Implementation: Interfaces should only contain method signatures and property/event declarations. They should not have any implementation code. Implementing classes must provide their own implementation.
- Interface Naming Conventions: Follow naming conventions for interfaces. Use descriptive names that indicate the purpose of the interface. Use PascalCase (capitalized words) for interface names.
- Members Cannot Have Access Modifiers: Members within an interface cannot have access modifiers (e.g.,
public
,private
,protected
) because they are implicitlypublic
. - Members Cannot Have Static Modifier: Interface members cannot be marked as
static
because they are meant to be implemented by instance methods in implementing classes. - No Fields or Constants: Interfaces cannot contain fields or constants. They are meant for defining contracts that specify behaviour, not for storing data.
- Yes, Structs can implement Interface like a normal class.
- Inheritance: An interface can inherit from one or more other interfaces using a colon
:
. This allows you to define a hierarchy of interfaces.interface IResizableShape : IShape { void Resize(int width, int height); }
- Implicit Implementation: Implementing classes must explicitly declare that they implement an interface using the
class
keyword followed by the interface name.class Circle : IShape { public void Draw() { // Implementation of the Draw method } }
- Explicit Interface Implementation: In some cases, you may want to provide an explicit implementation of an interface member by prefixing it with the interface name. This is used when a class implements multiple interfaces with members of the same name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Example : IFirstInterface, ISecondInterface { void IFirstInterface.CommonMethod() { // Explicit implementation for IFirstInterface } void ISecondInterface.CommonMethod() { // Explicit implementation for ISecondInterface } } |
These rules and conventions ensure that your interfaces are clear, consistent, and maintainable, making it easier for both you and other developers to work with your code.
- Abstract class are faster than Interfaces
Exercises
1 Can’t defined method implementation
Out- compile time error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public interface IMyInterface { void MyMethod() { Console.WriteLine("This is an interface method with implementation."); } } public class MyClass : IMyInterface { // Attempting to implement the interface method here will result in a compilation error. } class Program { static void Main() { // Error: 'MyClass' does not implement interface member 'IMyInterface.MyMethod()' IMyInterface myInstance = new MyClass(); } } |
2 Can’t contains instance field
output- compile time error
1 2 3 4 5 6 7 8 9 |
interface IDemo { int x; // cannot contain instance fields } public class Demo{ } |
In C#, interface members cannot be declared as fields; they must be properties
, methods
, events
, or indexers
Allowed-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public interface IMyInterface { // Property int MyProperty { get; set; } // Method void MyMethod(); // Event event EventHandler MyEvent; // Indexer int this[int index] { get; set; } } |
3 Can I use Interface method in different class. Like interface is inside an abstract class, how to use that in different class?
- also can I implement both interface and abstract class together?
Solution-
We can implement both interface and abstract class together.
Example-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using System; public abstract class Program { // note this interface should be "public" , else u will get compile error **public** interface IInterfaceInsideAbstractClass { void DoWrite(); } } public class Demo : Program, Program.IInterfaceInsideAbstractClass { public void DoWrite() { Console.WriteLine("Hello World"); } } |
Implemented Method without public keyword?
We have to use public access modifier in implemented method. Else will get error
The commented area in below code has a minor issue. The DoWrite
method in the Demo
class should have an public
access modifier to match the interface’s access level. Here’s the corrected code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using System; public abstract class Program { public interface IInterfaceInsideAbstractClass { void DoWrite(); } } public class Demo : Program, Program.IInterfaceInsideAbstractClass { // correct one- public void DoWrite() { Console.WriteLine("Hello World"); } // incorrect , its missing public // void DoWrite() // { // Console.WriteLine("Hello World"); // } } // Error- cannot implement interface member because its not public |
In this corrected code:
- The
IInterfaceInsideAbstractClass
interface is defined with apublic
access modifier to make it accessible outside the abstract class. - The
DoWrite
method in theDemo
class also has apublic
access modifier to match the interface’s access level. This ensures that the method properly implements the interface.
Two interfaces with the same function name.
explicit interface implementation
when a class implements multiple interfaces and those interfaces define members with the same name, you can use explicit interface implementation to disambiguate and specify which interface’s member you want to call.
Here’s an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using System; // First interface public interface IInterface1 { void CommonMethod(); } // Second interface public interface IInterface2 { void CommonMethod(); } // Class implementing both interfaces public class MyImplementation : IInterface1, IInterface2 { // Implementing CommonMethod for IInterface1 void IInterface1.CommonMethod() { Console.WriteLine("Implementation of CommonMethod from IInterface1"); } // Implementing CommonMethod for IInterface2 void IInterface2.CommonMethod() { Console.WriteLine("Implementation of CommonMethod from IInterface2"); } } public class Program { public static void Main() { MyImplementation myInstance = new MyImplementation(); // Using the CommonMethod from IInterface1 ((IInterface1)myInstance).CommonMethod(); // Using the CommonMethod from IInterface2 ((IInterface2)myInstance).CommonMethod(); } } |
Cannot use fully qualified name with the public
keyword in above example?
No,
this is indeed wrong- and will give compile error – “the modifier public
is not valid for explicit interface implementation”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class MyImplementation : IInterface1, IInterface2 { // Implementing CommonMethod for IInterface1 void IInterface1.CommonMethod() { Console.WriteLine("Implementation of CommonMethod from IInterface1"); } // Implementing CommonMethod for IInterface2 void IInterface2.CommonMethod() { Console.WriteLine("Implementation of CommonMethod from IInterface2"); } } |
Can we implement single common method in implemented class?
Solution- yes we can
Example-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using System; // Define the first interface public interface IInterface1 { void CommonMethod(); } // Define the second interface public interface IInterface2 { void CommonMethod(); } // Class implementing both interfaces public class MyImplementation : IInterface1, IInterface2 { // Implement CommonMethod for IInterface1 public void CommonMethod() { Console.WriteLine("Implementation of CommonMethod from MyImplementation class"); } } public class Program { public static void Main() { MyImplementation myInstance = new MyImplementation(); // Demonstrating explicit interface implementation IInterface1 interface1 = myInstance; interface1.CommonMethod(); IInterface2 interface2 = myInstance; interface2.CommonMethod(); } } |
1 2 3 4 |
Output- Implementation of CommonMethod from MyImplementation class Implementation of CommonMethod from MyImplementation class |
Does Interface supporting Inheritance?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
using System; interface IInterface1 { void MethodInterface1(); } interface IInterface2 : IInterface1 { void MethodInterface2(); } class Demo : IInterface2 { public void MethodInterface1() { Console.WriteLine("MethodInterface1 implementation in Demo class"); } public void MethodInterface2() { Console.WriteLine("MethodInterface2 implementation in Demo class"); } public static void Main() { Demo demoObj = new Demo(); IInterface2 interface2 = demoObj; IInterface1 interface1= demoObj; interface1.MethodInterface1(); // invalid, we cant use fully qualified name for inherited method! use // 1. using through interface2 interface2.MethodInterface2(); // Valid interface2.MethodInterface1(); // Valid due to interface inheritance interface1.MethodInterface1(); interface1.MethodInterface2(); // WRONG! // 2. using through class object demoObj.MethodInterface1(); demoObj.MethodInterface2(); //3. Using fully qualified names to call methods directly from the interface ((IInterface2)demoObj).MethodInterface2(); // Valid ((IInterface1)demoObj).MethodInterface1(); // Valid } } |
Congratulations, you learned interface in depth. I trust that you will be now able to crack any output/tricky interface based interview questions and concepts.
Its a complete guide of interface, in case you found something missing please put in comment box. My goal is to make best interface concept based article that cover everything.
Don’t forget to revise.
0 Comments