Section 3: Abstraction, Abstract Classes & Interfaces | 10 Important Questions | C# / .NET
1. 🔴 What is abstraction, and how is it implemented in C#?
What is abstraction?
Abstraction is one of the four main pillars of Object-Oriented Programming (OOP).
It is the process of hiding internal implementation details and exposing only essential functionality to the user.
In C#, abstraction is primarily implemented using:
-
Abstract classes – Define common functionality and abstract members that derived classes must implement.
-
Interfaces – Define contracts that implementing classes must follow.
C# example
Consider a payment system supporting UPI and credit card payments.
public interface IPayment
{
void Pay(decimal amount);
}
public class UpiPayment : IPayment
{
public void Pay(decimal amount)
{
Console.WriteLine($"UPI Payment: {amount}");
}
}
public class CardPayment : IPayment
{
public void Pay(decimal amount)
{
Console.WriteLine($"Card Payment: {amount}");
}
}
Usage:
IPayment payment = new UpiPayment();
payment.Pay(1000);
payment = new CardPayment();
payment.Pay(2000);
Output:
UPI Payment: 1000
Card Payment: 2000
Code explanation
-
IPaymentdefines thePay()contract. -
UpiPaymentimplements UPI payment processing. -
CardPaymentimplements credit card payment processing. -
The calling code interacts with the
IPaymentinterface without depending on a specific implementation.
Real-time scenario
In ASP.NET Core Web API, controllers commonly depend on service interfaces rather than concrete service classes.
EmployeeController
|
v
IEmployeeService
|
v
EmployeeService
|
v
IEmployeeRepository
|
v
EmployeeRepository
|
v
SQL Server
The controller depends on the service contract and does not need to know how the service accesses the database.
Interview answer
Abstraction is the process of hiding implementation details and exposing only essential functionality. In C#, it is implemented using abstract classes and interfaces. It reduces coupling, improves maintainability, and allows implementations to change without affecting dependent code.
2. 🔴 What is an abstract class, and when should you use it?
What is an abstract class?
An abstract class is a class declared using the abstract keyword that cannot be instantiated directly.
It is designed to serve as a base class for other classes.
An abstract class can contain:
-
Abstract methods without implementations.
-
Concrete methods with implementations.
-
Fields and properties.
-
Constructors.
-
Virtual methods that derived classes can override.
C# example
public abstract class Employee
{
public string Name { get; set; } = "";
public abstract decimal CalculateBonus();
public void Display()
{
Console.WriteLine($"Employee: {Name}");
}
}
public class Manager : Employee
{
public override decimal CalculateBonus()
{
return 20000;
}
}
public class Developer : Employee
{
public override decimal CalculateBonus()
{
return 10000;
}
}
Usage:
Employee emp1 = new Manager { Name = "John" };
Employee emp2 = new Developer { Name = "David" };
emp1.Display();
Console.WriteLine(emp1.CalculateBonus());
emp2.Display();
Console.WriteLine(emp2.CalculateBonus());
Output:
Employee: John
20000
Employee: David
10000
Code explanation
-
Employeeis an abstract base class. -
CalculateBonus()is an abstract method, so concrete derived classes must implement it. -
Display()contains shared functionality. -
ManagerandDeveloperinherit the common behavior.
When should you use an abstract class?
Use an abstract class when:
-
Multiple related classes share common functionality.
-
You need common fields, constructors, or state.
-
You want to enforce certain methods in derived classes.
-
You need to provide default implementations that subclasses can reuse.
Real-time scenario
In a banking application:
BankAccount
(Abstract Class)
|
+------+------+
| |
SavingsAccount CurrentAccount
| |
CalculateInterest()
Both account types can share account number, balance, deposit, and withdrawal functionality while implementing different account-specific rules.
Interview answer
An abstract class is a class that cannot be instantiated directly and is intended to be inherited. It can contain abstract methods, implemented methods, fields, properties, and constructors. We use abstract classes when related classes need shared functionality along with mandatory methods that derived classes must implement.
3. 🔴 What is an interface, and why is it used?
What is an interface?
An interface defines a contract that specifies the functionality an implementing class must provide.
Interfaces are declared using the interface keyword.
They are commonly used to achieve abstraction, loose coupling, dependency injection, and polymorphism.
C# example
public interface INotificationService
{
void Send(string message);
}
public class EmailNotification : INotificationService
{
public void Send(string message)
{
Console.WriteLine($"Email: {message}");
}
}
public class SmsNotification : INotificationService
{
public void Send(string message)
{
Console.WriteLine($"SMS: {message}");
}
}
Usage:
INotificationService service = new EmailNotification();
service.Send("Payment Successful");
service = new SmsNotification();
service.Send("Payment Successful");
Output:
Email: Payment Successful
SMS: Payment Successful
Why are interfaces used?
|
Benefit |
Explanation |
|---|---|
|
Abstraction |
Exposes functionality without requiring callers to know implementation details |
|
Loose coupling |
Classes depend on contracts instead of concrete implementations |
|
Dependency injection |
Allows implementations to be injected at runtime |
|
Testability |
Makes it easier to substitute test doubles |
|
Polymorphism |
Multiple classes can implement the same contract |
|
Extensibility |
New implementations can be added without changing existing consumers |
Real-time ASP.NET Core example
Interface:
public interface IEmployeeService
{
string GetEmployeeName(int id);
}
Implementation:
public class EmployeeService : IEmployeeService
{
public string GetEmployeeName(int id)
{
return "John";
}
}
Dependency injection registration:
builder.Services.AddScoped<IEmployeeService, EmployeeService>();
Controller:
[ApiController]
[Route("api/employees")]
public class EmployeeController : ControllerBase
{
private readonly IEmployeeService _service;
public EmployeeController(IEmployeeService service)
{
_service = service;
}
[HttpGet("{id}")]
public IActionResult Get(int id)
{
return Ok(_service.GetEmployeeName(id));
}
}
Code explanation
-
IEmployeeServicedefines the contract. -
EmployeeServiceprovides the implementation. -
AddScoped()registers the implementation with the DI container. -
ASP.NET Core injects the service into the controller.
-
The controller does not create
EmployeeServicedirectly.
Interview answer
An interface defines a contract that implementing classes must follow. Interfaces are used to achieve abstraction, loose coupling, dependency injection, polymorphism, and testability. In ASP.NET Core, interfaces are commonly used between controllers, services, and repositories.
4. 🔴 What is the difference between an abstract class and an interface?
Comparison table
|
Feature |
Abstract class |
Interface |
|---|---|---|
|
Keyword |
|
|
|
Main purpose |
Shared base functionality |
Define a contract |
|
Object creation |
Cannot instantiate directly |
Cannot instantiate directly |
|
Constructors |
Yes |
No instance constructors |
|
Instance fields |
Yes |
No |
|
Properties |
Yes |
Yes |
|
Abstract methods |
Yes |
Yes, through members without bodies |
|
Implemented methods |
Yes |
Yes, with default implementations |
|
Access modifiers |
Supported |
Supported, subject to interface rules |
|
Multiple inheritance |
Only one direct base class |
Multiple interfaces allowed |
|
State management |
Can maintain instance state |
Cannot maintain instance fields |
|
Best use |
Related classes sharing code |
Unrelated classes sharing a capability |
C# example: Abstract class
public abstract class Vehicle
{
public string Brand { get; set; } = "";
public void Start()
{
Console.WriteLine("Vehicle started");
}
public abstract void Drive();
}
public class Car : Vehicle
{
public override void Drive()
{
Console.WriteLine("Car is driving");
}
}
Here, Vehicle provides common state and functionality.
C# example: Interface
public interface IPrintable
{
void Print();
}
public class Invoice : IPrintable
{
public void Print()
{
Console.WriteLine("Printing invoice");
}
}
public class Report : IPrintable
{
public void Print()
{
Console.WriteLine("Printing report");
}
}
Here, unrelated classes implement the same capability.
When should you choose each?
Choose an abstract class when:
-
Classes share common fields or implementation.
-
There is a strong inheritance relationship.
-
You need constructors or shared state.
Choose an interface when:
-
You need a contract between components.
-
Multiple unrelated classes must provide the same functionality.
-
You need dependency injection and easy substitution.
-
A class must support multiple capabilities.
Interview answer
An abstract class provides a common base with shared state and functionality, while an interface primarily defines a contract. A class can inherit only one base class but implement multiple interfaces. Abstract classes are useful for related classes with shared behavior, while interfaces are preferred for loose coupling, dependency injection, and extensibility.
5. 🔴 Can an abstract class contain constructors, fields, properties, and implemented methods?
Yes. An abstract class can contain constructors, fields, properties, abstract methods, and implemented methods.
Although an abstract class cannot be instantiated directly, its constructor executes when a derived class is instantiated.
C# example
public abstract class Employee
{
// Field
protected decimal _salary;
// Property
public string Name { get; set; }
// Constructor
protected Employee(string name, decimal salary)
{
Name = name;
_salary = salary;
Console.WriteLine("Base constructor called");
}
// Implemented method
public void Display()
{
Console.WriteLine($"{Name} - {_salary}");
}
// Abstract method
public abstract decimal CalculateBonus();
}
public class Manager : Employee
{
public Manager(string name, decimal salary)
: base(name, salary)
{
Console.WriteLine("Derived constructor called");
}
public override decimal CalculateBonus()
{
return _salary * 0.20m;
}
}
Usage:
Manager manager = new Manager("John", 100000);
manager.Display();
Console.WriteLine(manager.CalculateBonus());
Output:
Base constructor called
Derived constructor called
John - 100000
20000.00
Important points
-
Abstract classes can have constructors.
-
The base constructor executes before the derived constructor body.
-
Abstract classes can contain private, protected, and public members.
-
Abstract methods have no body and require implementation by concrete derived classes.
-
Implemented methods can be inherited and reused.
Interview answer
Yes, an abstract class can contain constructors, fields, properties, abstract methods, and implemented methods. Its constructor is executed when a derived class is instantiated. Abstract classes are useful when multiple derived classes need common state and functionality.
6. 🔴 Can a class implement multiple interfaces and inherit multiple classes?
Explanation
C# does not support multiple class inheritance, but it supports implementing multiple interfaces.
A class can inherit from only one base class while implementing any number of interfaces.
Multiple class inheritance – Not allowed
public class Father { }
public class Mother { }
// Compilation error
public class Child : Father, Mother
{
}
C# does not allow a class to inherit directly from two classes.
Multiple interface implementation – Allowed
public interface IPrintable
{
void Print();
}
public interface ISavable
{
void Save();
}
public class Document : IPrintable, ISavable
{
public void Print()
{
Console.WriteLine("Printing document");
}
public void Save()
{
Console.WriteLine("Saving document");
}
}
Usage:
Document doc = new Document();
doc.Print();
doc.Save();
One base class + multiple interfaces
public class BaseDocument
{
public void Open()
{
Console.WriteLine("Opening document");
}
}
public class PdfDocument
: BaseDocument, IPrintable, ISavable
{
public void Print()
{
Console.WriteLine("Printing PDF");
}
public void Save()
{
Console.WriteLine("Saving PDF");
}
}
Why doesn't C# support multiple class inheritance?
One reason is to avoid ambiguity when multiple base classes define conflicting implementations, commonly illustrated by the diamond problem.
C# instead supports multiple interfaces, with explicit rules for resolving interface member implementations.
Interview answer
C# supports single class inheritance and multiple interface implementation. A class can inherit from only one base class but implement multiple interfaces. This allows a class to support multiple capabilities without the complications of multiple class inheritance.
7. 🟡 Can interfaces contain method implementations in modern C#?
Yes. Starting with C# 8.0, interfaces can contain default method implementations.
This feature is called Default Interface Methods (DIM).
C# example
public interface ILogger
{
void Log(string message);
// Default implementation
void LogError(string message)
{
Console.WriteLine($"ERROR: {message}");
}
}
public class FileLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"FILE: {message}");
}
}
Usage:
ILogger logger = new FileLogger();
logger.Log("Application started");
logger.LogError("Database connection failed");
Output:
FILE: Application started
ERROR: Database connection failed
Important points
-
Default interface methods were introduced in C# 8.0.
-
Interfaces can provide implementations for certain members.
-
Implementing classes do not need to override default methods.
-
Default interface members are not automatically exposed as public members of the implementing class.
For example:
FileLogger logger = new FileLogger();
// Not available directly on FileLogger
// logger.LogError("Error");
The method can be accessed through the interface reference.
When is it useful?
Default interface methods are particularly useful when evolving an existing interface without requiring every implementation to immediately add the new method.
Interview answer
Yes. Since C# 8.0, interfaces can contain default method implementations. This allows new functionality to be added to interfaces while reducing breaking changes for existing implementations. Implementing classes may use the default implementation or provide their own.
8. 🟡 Can an abstract class implement an interface without implementing all its members?
Yes. An abstract class can implement an interface without providing implementations for all interface members.
However, a concrete derived class must satisfy any remaining interface requirements.
C# example
public interface IEmployee
{
void Work();
void CalculateSalary();
}
public abstract class Employee : IEmployee
{
public void Work()
{
Console.WriteLine("Employee working");
}
// Implementation deferred
public abstract void CalculateSalary();
}
public class Developer : Employee
{
public override void CalculateSalary()
{
Console.WriteLine("Salary calculated");
}
}
Usage:
IEmployee emp = new Developer();
emp.Work();
emp.CalculateSalary();
Output:
Employee working
Salary calculated
Code explanation
-
IEmployeedefines two methods. -
The abstract
Employeeclass implementsWork(). -
CalculateSalary()remains abstract. -
Developerimplements the remaining method.
Real-time scenario
In an enterprise application, an abstract base service can implement common interface operations while leaving business-specific operations for derived services.
Interview answer
Yes, an abstract class can implement an interface without implementing all its members. The remaining members can be left for derived classes to implement. However, a concrete derived class must fulfill all required interface members before it can be instantiated.
9. 🟡 What are explicit and implicit interface implementations?
Implicit interface implementation
In implicit implementation, a class implements interface members using public methods or properties.
These members can be accessed through both the class and interface references.
C# example
public interface IPrinter
{
void Print();
}
public class Printer : IPrinter
{
public void Print()
{
Console.WriteLine("Printing document");
}
}
Usage:
Printer printer = new Printer();
printer.Print(); // Allowed
IPrinter obj = printer;
obj.Print(); // Allowed
Explicit interface implementation
In explicit implementation, the interface name is included in the member declaration.
The implementation can only be accessed through an appropriate interface reference.
C# example
public interface IPrinter
{
void Print();
}
public class Printer : IPrinter
{
void IPrinter.Print()
{
Console.WriteLine("Printing document");
}
}
Usage:
Printer printer = new Printer();
// printer.Print(); // Compilation error
IPrinter obj = printer;
obj.Print(); // Allowed
Real-time example: Two interfaces with the same method
public interface IEmail
{
void Send();
}
public interface ISms
{
void Send();
}
public class Notification : IEmail, ISms
{
void IEmail.Send()
{
Console.WriteLine("Email sent");
}
void ISms.Send()
{
Console.WriteLine("SMS sent");
}
}
Usage:
Notification notification = new Notification();
IEmail email = notification;
ISms sms = notification;
email.Send();
sms.Send();
Output:
Email sent
SMS sent
Comparison table
|
Feature |
Implicit |
Explicit |
|---|---|---|
|
Method declaration |
|
|
|
Public class member |
Yes |
No |
|
Accessible through class reference |
Yes |
No |
|
Accessible through interface reference |
Yes |
Yes |
|
Access modifier on implementation |
Public |
Cannot specify one |
|
Best use |
Normal interface implementation |
Resolve name conflicts or hide interface-specific members |
Interview answer
Implicit interface implementation uses public members that can be accessed through both class and interface references. Explicit interface implementation uses the interface name in the member declaration and can only be accessed through an interface reference. Explicit implementation is useful when multiple interfaces contain members with identical signatures that require different behavior.
10. 🟡 When would you choose an interface instead of an abstract class in a real project?
Explanation
Choose an interface when you need a contract that supports multiple implementations without forcing consumers to depend on a specific class hierarchy.
Choose an abstract class when related classes share common state or reusable implementation.
Real-time scenario: ASP.NET Core Web API
Suppose an application supports multiple notification providers:
-
Email
-
SMS
-
WhatsApp
Each provider performs the same logical operation but uses a different implementation.
Step 1: Define interface
public interface INotificationService
{
Task SendAsync(string message);
}
Step 2: Implement services
public class EmailService : INotificationService
{
public Task SendAsync(string message)
{
Console.WriteLine($"Email: {message}");
return Task.CompletedTask;
}
}
public class SmsService : INotificationService
{
public Task SendAsync(string message)
{
Console.WriteLine($"SMS: {message}");
return Task.CompletedTask;
}
}
Step 3: Register service
builder.Services.AddScoped<
INotificationService, EmailService>();
Step 4: Inject into controller
[ApiController]
[Route("api/notifications")]
public class NotificationController : ControllerBase
{
private readonly INotificationService _service;
public NotificationController(
INotificationService service)
{
_service = service;
}
[HttpPost]
public async Task<IActionResult> Send(
[FromBody] string message)
{
await _service.SendAsync(message);
return Ok("Notification sent");
}
}
What happens when the implementation changes?
Suppose the application needs to switch from Email to SMS.
Only the dependency injection registration needs to change:
builder.Services.AddScoped<
INotificationService, SmsService>();
The controller remains unchanged.
Application flow
Client
|
v
NotificationController
|
v
INotificationService
|
+-------------------+
| |
v v
EmailService SmsService
The application selects the implementation through dependency injection configuration.
Interface vs Abstract class – Decision table
|
Scenario |
Recommended |
|---|---|
|
Dependency injection in ASP.NET Core |
Interface |
|
Multiple interchangeable implementations |
Interface |
|
Mocking or substituting dependencies in tests |
Interface |
|
Common contract across unrelated classes |
Interface |
|
Shared fields and constructors |
Abstract class |
|
Shared implemented methods |
Abstract class |
|
Strong base-class relationship |
Abstract class |
|
Common template with required override methods |
Abstract class |
Important design consideration
An interface is not mandatory for every class or service.
For example, if a simple internal class has only one implementation and no meaningful need for substitution, introducing an interface may add unnecessary complexity.
Also, interfaces and abstract classes can be used together when an application requires both a public contract and shared implementation.
Interview answer
I prefer interfaces when implementing dependency injection, loose coupling, multiple implementations, and testable services in ASP.NET Core. For example, controllers depend on IEmployeeService rather than EmployeeService. I choose abstract classes when related classes need shared fields, constructors, or common implemented methods.
Quick Interview Revision – All 10 Questions
|
Question |
Key points to remember |
|---|---|
|
1. Abstraction |
Hide implementation, expose essential functionality |
|
2. Abstract class |
Common base, shared code, abstract methods |
|
3. Interface |
Contract, loose coupling, DI, testability |
|
4. Abstract vs Interface |
Shared implementation vs contract |
|
5. Abstract class members |
Constructors, fields, properties, methods |
|
6. Multiple inheritance |
One base class, multiple interfaces |
|
7. Default interface methods |
Supported since C# 8.0 |
|
8. Abstract class implementing interface |
Can defer implementation to derived class |
|
9. Explicit vs Implicit |
Interface-only access vs public class access |
|
10. Interface vs Abstract in projects |
DI and interchangeable services vs shared base functionality |
Interview priority: Questions 1, 3, 4, 6, 9, and 10 are particularly valuable because interviewers frequently connect abstraction to real ASP.NET Core architecture, dependency injection, SOLID principles, and practical design decisions.