11
OctMastering OOPs Concepts in C#: A Comprehensive Guide
OOPs Concepts in C#
Oops, Concepts in C# is a method for structuring software around objects rather than actions. C#, a powerful and versatile programming language, adopts OOP concepts to assist developers in creating well-organized and reusable code. The four pillars of OOP—encapsulation, inheritance, polymorphism, and abstraction—are critical for creating manageable and efficient applications.
In this OOPs Tutorial, we are going to explain all the concepts of object-oriented programming, including Encapsulation, Class and object, inheritance, and Polymorphism. Let's first see what the OOPs concept is exactly.
What is object-oriented programming?
Object-oriented programming (OOP) is a programming approach that organizes software design around data, rather than functions and logic. An object is a data field that has distinct attributes and behavior.
The 4 Pillars of OOP in C# With Example
- Encapsulation
- Inheritance
- Abstraction
- Polymorphism
1. Encapsulation in C#
- Encapsulation in C# means that data and the functions that operate on that data are combined into a single unit (class/object).
- This improves data security, modularity, & reuse.
- Encapsulation is similar to a School bag where you can store your pen, book, and other items. This refers to the property of encapsulating members and functions.
Syntax
class SchoolBag {
book;
pen;
ReadBook();
}
- Encapsulation refers to hiding an object's internal details, or how it performs a function.
- Encapsulation prevents clients from viewing the inside view, which contains the implementation of the abstraction's behavior.
- Encapsulation is a technique for protecting information in one object from another.
- Hide the data for security purposes, such as making the variables private and exposing the property to allow access to the private data that will be public.
- So, when you access the property, you can both validate and set the data.
Example
public class Student {
private string name;
private int age;
public string GetName() {
return name;
}
public void SetName(string newName) {
name = newName;
}
}
Explanation
- In the preceding example, the name field is concealed from direct access and can only be edited through methods, hence maintaining data integrity.
Real-World Example of Encapsulation in C#
Encapsulation Example: Bank Account System
using System;
public class BankAccount {
// Private field to store the balance
private double balance;
// Constructor to initialize the balance
public BankAccount(double initialBalance) {
if(initialBalance >= 0) {
balance = initialBalance;
} else {
balance = 0;
Console.WriteLine("Initial balance can't be negative. Setting balance to 0.");
}
}
// Public method to get the current balance (read-only access)
public double GetBalance() {
return balance;
}
// Public method to deposit money (with validation)
public void Deposit(double amount) {
if(amount > 0) {
balance += amount;
Console.WriteLine($"Deposited: {amount}. New Balance: {balance}");
} else {
Console.WriteLine("Deposit amount must be positive.");
}
}
// Public method to withdraw money (with validation)
public void Withdraw(double amount) {
if(amount > 0 && amount <= balance) {
balance -= amount;
Console.WriteLine($"Withdrawn: {amount}. New Balance: {balance}");
} else {
Console.WriteLine("Invalid withdrawal amount.");
}
}
}
public class Program {
public static void Main() {
// Creating a new bank account with an initial balance
BankAccount account = new BankAccount(500);
// Checking initial balance
Console.WriteLine("Initial Balance: " + account.GetBalance());
// Trying to deposit money
account.Deposit(200);
// Trying to withdraw money
account.Withdraw(150);
// Trying to withdraw an invalid amount
account.Withdraw(600);
// Trying to deposit a negative amount
account.Deposit(-50);
}
}
Output
Initial Balance: 500
Deposited: 200. New Balance: 700
Withdrawn: 150. New Balance: 550
Invalid withdrawal amount.
Deposit amount must be positive.
Explanation
2. Inheritance in C#
Key Features of Inheritance in C#
- The base class is the one from which the inheritance is made.
- Derived Class: A class that derives from the base class.
- Single Inheritance: C# supports single inheritance, meaning a class can inherit from only one base class.
- Method Overriding: Derived classes can provide specific implementations for methods that are declared in the base class using the override keyword.
Syntax of Inheritance in C#
public class BaseClass {
// Base class members (fields, methods, etc.)
}
public class DerivedClass : BaseClass {
// Derived class members (fields, methods, etc.)
}
Example of Inheritance in C#
using System;
public class Animal {
public void Eat() {
Console.WriteLine("This animal is eating.");
}
}
public class Dog : Animal {
public void Bark() {
Console.WriteLine("The dog is barking.");
}
}
public class Program {
public static void Main() {
Dog myDog = new Dog();
// Calling method from the derived class
myDog.Bark();
// Calling inherited method from the base class
myDog.Eat();
}
}
Output
The dog is barking.
This animal is eating.
Explanation
- Base Class: The base class, Animal, defines the function Eat().
- Derived Class: Dog is a derived class that derives from Animal. It introduces a new function called Bark().
- Code Reusability: The Dog class reuses the Animal class's Eat() method, demonstrating how inheritance reduces redundancy.
Types of Inheritance in C#
- Single Inheritance: A derived class inherits from a single base class.
- Multilevel Inheritance: A derived class inherits from a base class, and another class may inherit from the derived class.
- Hierarchical Inheritance: Multiple derived classes inherit from a single base class.
Read More: Types of Inheritance |
Real-World Example of Inheritance in C#
Example: Employee Management System.
using System;
public class Employee {
public string Name { get; set; }
public int EmployeeID { get; set; }
public Employee(string name, int employeeID) {
Name = name;
EmployeeID = employeeID;
}
// Base class method
public virtual void DisplayDetails() {
Console.WriteLine($"Name: {Name}, Employee ID: {EmployeeID}");
}
}
// Derived class representing full-time employees
public class FullTimeEmployee : Employee {
public double AnnualSalary { get; set; }
public FullTimeEmployee(string name, int employeeID, double annualSalary)
: base(name, employeeID) {
AnnualSalary = annualSalary;
}
// Overriding the base class method
public override void DisplayDetails() {
base.DisplayDetails();
Console.WriteLine($"Annual Salary: {AnnualSalary}");
}
}
// Derived class representing part-time employees
public class PartTimeEmployee : Employee {
public double HourlyWage { get; set; }
public int HoursWorked { get; set; }
public PartTimeEmployee(string name, int employeeID, double hourlyWage, int hoursWorked)
: base(name, employeeID) {
HourlyWage = hourlyWage;
HoursWorked = hoursWorked;
}
// Overriding the base class method
public override void DisplayDetails() {
base.DisplayDetails();
Console.WriteLine($"Hourly Wage: {HourlyWage}, Hours Worked: {HoursWorked}, Total Pay: {HourlyWage * HoursWorked}");
}
}
public class Program {
public static void Main() {
// Creating a full-time employee object
FullTimeEmployee ftEmployee = new FullTimeEmployee("John Doe", 101, 60000);
Console.WriteLine("Full-Time Employee Details:");
ftEmployee.DisplayDetails();
Console.WriteLine();
// Creating a part-time employee object
PartTimeEmployee ptEmployee = new PartTimeEmployee("Jane Smith", 102, 20, 25);
Console.WriteLine("Part-Time Employee Details:");
ptEmployee.DisplayDetails();
}
}
Output
Full-Time Employee Details:
Name: John Doe, Employee ID: 101
Annual Salary: 60000
Part-Time Employee Details:
Name: Jane Smith, Employee ID: 102
Hourly Wage: 20, Hours Worked: 25, Total Pay: 500
Explanation
Employee is the base class that defines common characteristics and methods for all employees, such as Name and EmployeeID. It also contains a method DisplayDetails() that prints the employee information. Derived Classes: Full-Time Employee and Part-Time Employee. FullTimeEmployee creates a new field AnnualSalary and overrides the DisplayDetails() method to incorporate salary data. PartTimeEmployeeadds the HourlyWage and HoursWorked fields and modifies DisplayDetails() to display wage and total pay. Polymorphism: The DisplayDetails() method is overridden in both derived classes, demonstrating how the method in the base class can be tailored to different employee kinds.3. Data Abstraction in C#
Abstraction is a major concept in Object-Oriented Programming (OOP), which focuses on hiding an implementation's underlying details while presenting only the necessary functionalities. Simply put, abstraction enables you to work with objects at a high level, utilizing a clear and easy interface, without having to comprehend how the underlying actions are performed.
- Abstract classes
- Interfaces
Both abstract classes and interfaces allow you to create methods that must be carried out by derived or implementing classes, but they cannot be instantiated directly.
1. Abstract Classes in C#
Syntax:
To define an abstract class and its methods, use the "abstract" keyword. public abstract class Animal {
public abstract void MakeSound(); // Abstract method
public void Eat() { // Concrete method
Console.WriteLine("This animal is eating.");
}
}
Example of Abstract Class:
using System;
public abstract class Animal {
// Abstract method (no implementation)
public abstract void MakeSound();
// Concrete method (has implementation)
public void Sleep() {
Console.WriteLine("This animal is sleeping.");
}
}
// Derived class providing implementation for abstract method
public class Dog : Animal {
public override void MakeSound() {
Console.WriteLine("The dog barks.");
}
}
public class Program {
public static void Main() {
// Animal myAnimal = new Animal(); // Error! Cannot instantiate abstract class
Dog myDog = new Dog(); // Create a Dog object
myDog.MakeSound(); // Calls the implemented method
myDog.Sleep(); // Calls the inherited concrete method
}
}
Output
The dog barks.
This animal is sleeping.
Explanation
"Animal" is an abstract class, which means you cannot make an instance of it directly. It has an abstract method named MakeSound() that any derived class must implement. The Dog class derives from Animal and has its own implementation of MakeSound(). "Dog" inherits and uses the Sleep() method from Animal, which is a concrete method.2. Interfaces in C#
An interface in C# defines the contract to which a class must adhere. All methods in an interface are abstract by default (that is, they have no implementation), and any class that implements the interface must supply implementations for all of the interface's methods.Interface Syntax:
Declare an interface using the interface keyword. public interface IAnimal {
void MakeSound(); // Interface method (no implementation)
}
Example of Interface:
using System;
public interface IAnimal {
// Abstract method (implicitly abstract, no implementation)
void MakeSound();
}
public class Dog : IAnimal {
// Implementing the interface method
public void MakeSound() {
Console.WriteLine("The dog barks.");
}
}
public class Program {
public static void Main() {
Dog myDog = new Dog();
myDog.MakeSound();
}
}
Output
The dog barks.
3. Real-World Example of Abstraction in C#
Example
using System;
public interface IPayment {
void ProcessPayment(double amount); // Abstract method
}
public class CreditCardPayment : IPayment {
public void ProcessPayment(double amount) {
Console.WriteLine($"Processing credit card payment of {amount}.");
}
}
public class BankTransferPayment : IPayment {
public void ProcessPayment(double amount) {
Console.WriteLine($"Processing bank transfer payment of {amount}.");
}
}
public class Program {
public static void Main() {
IPayment payment;
// Process credit card payment
payment = new CreditCardPayment();
payment.ProcessPayment(250.00);
// Process bank transfer payment
payment = new BankTransferPayment();
payment.ProcessPayment(1500.00);
}
}
Output
Processing credit card payment of 250.
Processing bank transfer payment of 1500.
Polymorphism in C#
Polymorphism is an important concept in Object-Oriented Programming (OOP) that allows objects to be viewed as instances of their base class or interface, even if their actual implementation varies. In C#, polymorphism allows a single method to have many implementations based on the object that calls it. This increases the flexibility, extensibility, and reusability of programs.1. Compile time Polymorphism (method overloading)
Compile-time polymorphism happens when many methods in the same class have the same name but have different numbers or types of parameters. This is referred to as method overloading. The appropriate method to invoke is determined at build time.Example of compile-time polymorphism
using System;
public class Calculator {
// Method with two integer parameters
public int Add(int a, int b) {
return a + b;
}
// Overloaded method with three integer parameters
public int Add(int a, int b, int c) {
return a + b + c;
}
// Overloaded method with double parameters
public double Add(double a, double b) {
return a + b;
}
}
public class Program {
public static void Main() {
Calculator calc = new Calculator();
// Calling overloaded methods
Console.WriteLine(calc.Add(2, 3)); // Calls Add(int, int)
Console.WriteLine(calc.Add(2, 3, 4)); // Calls Add(int, int, int)
Console.WriteLine(calc.Add(2.5, 3.5)); // Calls Add(double, double)
}
}
Output
5
9
6
2. Run-time polymorphism (Method Overriding)
Method overriding allows for runtime polymorphism. This happens when a derived class adds its own implementation of a method that is already declared in the base class. The method in the base class must be designated as virtual, and the derived class employs the override keyword. This sort of polymorphism allows you to call methods using a base class reference, but the actual function is selected at runtime based on the object's type.Example of run-time polymorphism
using System;
public class Animal {
// Virtual method in base class
public virtual void MakeSound() {
Console.WriteLine("Animal makes a sound.");
}
}
public class Dog : Animal {
// Overriding the MakeSound method in the derived class
public override void MakeSound() {
Console.WriteLine("Dog barks.");
}
}
public class Cat : Animal {
// Overriding the MakeSound method in the derived class
public override void MakeSound() {
Console.WriteLine("Cat meows.");
}
}
public class Program {
public static void Main() {
// Base class reference pointing to a derived class object
Animal myAnimal;
// Creating a Dog object
myAnimal = new Dog();
myAnimal.MakeSound(); // Calls Dog's MakeSound method
// Creating a Cat object
myAnimal = new Cat();
myAnimal.MakeSound(); // Calls Cat's MakeSound method
}
}
Output
Dog barks.
Cat meows.
Explanation
The base class Animal includes a virtual function MakeSound(), which can be overridden by derived classes. Derived Classes Dog and Cat: Both classes override the MakeSound() function to offer their own implementation. Polymorphic Behavior: In the Main method, the myAnimal reference (of type Animal) is utilized to hold Dog and Cat objects respectively. The actual method called is determined by the object's actual type (Dog or Cat), not its reference type (Animal).Read More: Method Overloading and Method Overriding in C# |
Real-World Example of Polymorphism in C#
Example
using System;
public abstract class Payment {
// Abstract method to be implemented by derived classes
public abstract void ProcessPayment(double amount);
}
public class CreditCardPayment : Payment {
// Overriding the abstract method
public override void ProcessPayment(double amount) {
Console.WriteLine($"Processing credit card payment of {amount}.");
}
}
public class PayPalPayment : Payment {
// Overriding the abstract method
public override void ProcessPayment(double amount) {
Console.WriteLine($"Processing PayPal payment of {amount}.");
}
}
public class Program {
public static void Main() {
Payment payment;
// Processing a credit card payment
payment = new CreditCardPayment();
payment.ProcessPayment(100.00);
// Processing a PayPal payment
payment = new PayPalPayment();
payment.ProcessPayment(200.00);
}
}
Output
Processing credit card payment of 100.
Processing PayPal payment of 200.
Additional OOP Concepts in C#
1. Classes & Objects
Classes are blueprints for constructing objects that are instances of the class. Objects contain data in fields (variables) and expose behavior via methods. public class Person {
public string Name;
public int Age;
}
Person person1 = new Person();
person1.Name = "John";
person1.Age = 25;
2. Constructor
Constructors in Csharp are special methods that are executed when an object is created. They initialize the object's state. public class Person {
public string Name;
public int Age;
public Person(string name, int age) {
Name = name;
Age = age;
}
}
3. Interfaces
An interface in C# specifies the contract that a class must obey. It describes methods and attributes but not their implementations. public interface IAnimal {
void MakeSound();
}
public class Dog : IAnimal {
public void MakeSound() {
Console.WriteLine("Bark");
}
}
4. Access modifiers
Access modifiers control the visibility of classes and their members.- Public: accessible from anyplace.
- Private: Accessible only within the class.
- Protected: accessible within the class and its descendant classes.
- Internal: accessible within the same assembly.
5. Static vs Instance Members
- Instance Members: These members belong to a specific instance of the class and may only be accessed by constructing a class object.
- Static Members: Belong to the class itself and can be accessed without generating a new instance of the class.
public class Calculator {
public static int Add(int a, int b) {
return a + b;
}
}
int result = Calculator.Add(3, 4);
6. Properties in C#
public class Person {
private string name;
public string Name {
get { return name; }
set { name = value; }
}
}
Real-World Example: Implementing OOP Concepts in C#
public class Account {
private double balance;
public Account(double initialBalance) {
balance = initialBalance;
}
public double Balance {
get { return balance; }
}
public void Deposit(double amount) {
if(amount > 0) {
balance += amount;
}
}
public void Withdraw(double amount) {
if(amount > 0 && amount <= balance) {
balance -= amount;
}
}
}
public class SavingsAccount : Account {
private double interestRate;
public SavingsAccount(double initialBalance, double rate) : base(initialBalance) {
interestRate = rate;
}
public void AddInterest() {
Deposit(Balance * interestRate);
}
}
Explanation
The banking system includes Encapsulation: The balance is secret, with access supplied by means. Inheritance: SavingsAccount inherits from Account. Polymorphism: The Deposit and Withdraw methods can be customized for other account types if necessary.Advantages of Using OOP in C#
1. Code Reusability: OOP encourages code reuse through inheritance, which reduces redundancy and increases maintainability.Conclusion
Object-Oriented Programming in C# provides a solid foundation for developing sophisticated software systems. OOP, which is built on the principles of encapsulation, abstraction, inheritance, and polymorphism, gives developers the tools they need to produce clean, efficient, and maintainable code. C# extends OOP ideas with concepts such as access modifiers, interfaces, and properties, allowing developers to create scalable and adaptable programs. If you are preparing for an exam or interview regarding OOPS concepts, then consider our OOPs Interview Questions and Answers in C#.FAQs
Q1. Why is OOP important?
Q2. What is OOPs in real life?
Q3. Why do we study OOPs?
Take our Csharp skill challenge to evaluate yourself!
In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.