C# & ASP.NET Topic
C# Object-Oriented Programming (OOP)
1. Classes and Objects
Classes
A class is a blueprint or template that defines the structure and behavior of objects.
Objects
An object is an instance of a class - a concrete entity created from the class blueprint.
Detailed Examples:
Basic Class and Object:
csharp
// Class definition (blueprint)
public class Car
{
// Fields (data)
public string Make;
public string Model;
public int Year;
// Method (behavior)
public void DisplayInfo()
{
Console.WriteLine($"{Year} {Make} {Model}");
}
}
// Using the class
class Program
{
static void Main()
{
// Creating objects (instances)
Car car1 = new Car();
car1.Make = "Toyota";
car1.Model = "Camry";
car1.Year = 2022;
car1.DisplayInfo(); // Output: 2022 Toyota Camry
Car car2 = new Car();
car2.Make = "Honda";
car2.Model = "Civic";
car2.Year = 2023;
car2.DisplayInfo(); // Output: 2023 Honda Civic
}
}
2. Constructors
Constructors are special methods that are called when an object is created. They initialize the object's data.
Detailed Examples:
Default Constructor:
csharp
public class Book
{
public string Title;
public string Author;
public decimal Price;
// Default constructor (provided automatically if none defined)
public Book()
{
Title = "Unknown";
Author = "Unknown";
Price = 0.0m;
}
}
Parameterized Constructor:
csharp
public class Book
{
public string Title;
public string Author;
public decimal Price;
// Parameterized constructor
public Book(string title, string author, decimal price)
{
Title = title;
Author = author;
Price = price;
}
}
// Usage
Book book1 = new Book("C# Programming", "John Doe", 49.99m);
Console.WriteLine(book1.Title); // Output: C# Programming
Constructor Overloading:
csharp
public class Book
{
public string Title;
public string Author;
public decimal Price;
public int PageCount;
// Constructor 1: Full parameters
public Book(string title, string author, decimal price, int pages)
{
Title = title;
Author = author;
Price = price;
PageCount = pages;
}
// Constructor 2: Without page count
public Book(string title, string author, decimal price)
{
Title = title;
Author = author;
Price = price;
PageCount = 0; // Default value
}
// Constructor 3: Copy constructor
public Book(Book otherBook)
{
Title = otherBook.Title;
Author = otherBook.Author;
Price = otherBook.Price;
PageCount = otherBook.PageCount;
}
}
// Usage
Book book1 = new Book("C# Guide", "Jane Smith", 39.99m, 400);
Book book2 = new Book("ASP.NET", "Bob Wilson", 59.99m);
Book book3 = new Book(book1); // Copy of book1
Constructor Chaining:
csharp
public class Student
{
public string Name;
public int Age;
public string Major;
public double GPA;
// Main constructor with all parameters
public Student(string name, int age, string major, double gpa)
{
Name = name;
Age = age;
Major = major;
GPA = gpa;
}
// Constructor chaining - calls main constructor with default values
public Student(string name, int age) : this(name, age, "Undeclared", 0.0)
{
}
// Another chained constructor
public Student(string name) : this(name, 18, "Undeclared", 0.0)
{
}
}
3. Encapsulation
Encapsulation is the concept of bundling data and methods that operate on that data, and restricting direct access to some of an object's components.
Access Modifiers:
-
public: Accessible from anywhere -
private: Accessible only within the same class -
protected: Accessible within the same class and derived classes -
internal: Accessible within the same assembly
Detailed Examples:
Basic Encapsulation with Properties:
csharp
public class BankAccount
{
// Private fields (encapsulated data)
private string _accountNumber;
private decimal _balance;
private string _accountHolder;
// Public properties (controlled access)
public string AccountNumber
{
get { return _accountNumber; }
private set { _accountNumber = value; } // Can only be set within class
}
public decimal Balance
{
get { return _balance; }
private set
{
if (value >= 0)
_balance = value;
}
}
public string AccountHolder
{
get { return _accountHolder; }
set
{
if (!string.IsNullOrEmpty(value))
_accountHolder = value;
}
}
// Constructor
public BankAccount(string accountNumber, string accountHolder, decimal initialBalance)
{
_accountNumber = accountNumber;
_accountHolder = accountHolder;
_balance = initialBalance;
}
// Public methods to manipulate private data
public void Deposit(decimal amount)
{
if (amount > 0)
{
Balance += amount;
Console.WriteLine($"Deposited: ${amount}. New balance: ${Balance}");
}
}
public bool Withdraw(decimal amount)
{
if (amount > 0 && amount <= Balance)
{
Balance -= amount;
Console.WriteLine($"Withdrawn: ${amount}. New balance: ${Balance}");
return true;
}
Console.WriteLine("Insufficient funds or invalid amount");
return false;
}
}
// Usage
BankAccount account = new BankAccount("123456", "John Doe", 1000);
account.Deposit(500); // Valid
// account.Balance = 5000; // Error - private setter
account.Withdraw(200); // Valid
Auto-Implemented Properties:
csharp
public class Person
{
// Auto-implemented properties (compiler creates private backing fields)
public string FirstName { get; set; }
public string LastName { get; set; }
// Read-only auto property
public string FullName
{
get { return $"{FirstName} {LastName}"; }
}
// Property with validation
private int _age;
public int Age
{
get { return _age; }
set
{
if (value >= 0 && value <= 150)
_age = value;
else
throw new ArgumentException("Invalid age");
}
}
}
4. Inheritance
Inheritance allows a class to acquire the properties and behavior of another class.
Base Class (Parent) and Derived Class (Child)
Detailed Examples:
Basic Inheritance:
csharp
// Base class (parent)
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public Animal(string name, int age)
{
Name = name;
Age = age;
}
public virtual void MakeSound()
{
Console.WriteLine("The animal makes a sound");
}
public void Sleep()
{
Console.WriteLine($"{Name} is sleeping");
}
}
// Derived class (child)
public class Dog : Animal // Dog inherits from Animal
{
public string Breed { get; set; }
// Call base class constructor using base()
public Dog(string name, int age, string breed) : base(name, age)
{
Breed = breed;
}
// Override base class method
public override void MakeSound()
{
Console.WriteLine("Woof! Woof!");
}
// New method specific to Dog
public void Fetch()
{
Console.WriteLine($"{Name} is fetching the ball");
}
}
// Another derived class
public class Cat : Animal
{
public bool IsIndoor { get; set; }
public Cat(string name, int age, bool isIndoor) : base(name, age)
{
IsIndoor = isIndoor;
}
public override void MakeSound()
{
Console.WriteLine("Meow!");
}
public void Climb()
{
Console.WriteLine($"{Name} is climbing a tree");
}
}
// Usage
Animal genericAnimal = new Animal("Generic", 1);
Dog dog = new Dog("Buddy", 3, "Golden Retriever");
Cat cat = new Cat("Whiskers", 2, true);
genericAnimal.MakeSound(); // Output: The animal makes a sound
dog.MakeSound(); // Output: Woof! Woof!
cat.MakeSound(); // Output: Meow!
dog.Sleep(); // Inherited from Animal
dog.Fetch(); // Specific to Dog
Multi-level Inheritance:
csharp
public class Vehicle
{
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public virtual void Start()
{
Console.WriteLine("Vehicle started");
}
}
public class Car : Vehicle
{
public int NumberOfDoors { get; set; }
public override void Start()
{
Console.WriteLine("Car engine started");
}
public void Honk()
{
Console.WriteLine("Beep beep!");
}
}
public class ElectricCar : Car
{
public int BatteryCapacity { get; set; }
public override void Start()
{
Console.WriteLine("Electric motor activated silently");
}
public void Charge()
{
Console.WriteLine("Charging battery...");
}
}
// Usage
ElectricCar tesla = new ElectricCar
{
Make = "Tesla",
Model = "Model S",
Year = 2023,
NumberOfDoors = 4,
BatteryCapacity = 100
};
tesla.Start(); // Output: Electric motor activated silently
tesla.Honk(); // Inherited from Car
tesla.Charge(); // Specific to ElectricCar
5. Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a common base class.
Types of Polymorphism:
-
Compile-time polymorphism (Method overloading)
-
Runtime polymorphism (Method overriding)
Detailed Examples:
Method Overriding (Runtime Polymorphism):
csharp
public class Shape
{
public virtual void Draw()
{
Console.WriteLine("Drawing a shape");
}
public virtual double CalculateArea()
{
return 0;
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public override void Draw()
{
Console.WriteLine($"Drawing a circle with radius {Radius}");
}
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public override void Draw()
{
Console.WriteLine($"Drawing a rectangle {Width}x{Height}");
}
public override double CalculateArea()
{
return Width * Height;
}
}
// Using polymorphism
class Program
{
static void Main()
{
// Polymorphic behavior
List<Shape> shapes = new List<Shape>
{
new Circle(5.0),
new Rectangle(4.0, 6.0),
new Circle(3.0),
new Rectangle(2.0, 8.0)
};
foreach (Shape shape in shapes)
{
shape.Draw(); // Calls the appropriate overridden method
double area = shape.CalculateArea();
Console.WriteLine($"Area: {area:F2}");
Console.WriteLine();
}
}
}
Output:
text
Drawing a circle with radius 5 Area: 78.54 Drawing a rectangle 4x6 Area: 24.00 Drawing a circle with radius 3 Area: 28.27 Drawing a rectangle 2x8 Area: 16.00
Method Overloading (Compile-time Polymorphism):
csharp
public class Calculator
{
// Same method name, different parameters
public int Add(int a, int b)
{
return a + b;
}
public double Add(double a, double b)
{
return a + b;
}
public int Add(int a, int b, int c)
{
return a + b + c;
}
public string Add(string a, string b)
{
return a + b;
}
}
// Usage
Calculator calc = new Calculator();
Console.WriteLine(calc.Add(5, 10)); // 15
Console.WriteLine(calc.Add(5.5, 2.3)); // 7.8
Console.WriteLine(calc.Add(1, 2, 3)); // 6
Console.WriteLine(calc.Add("Hello", " World")); // "Hello World"
Abstract Classes and Methods:
csharp
// Abstract class - cannot be instantiated
public abstract class Employee
{
public string Name { get; set; }
public string EmployeeId { get; set; }
// Abstract method - must be implemented by derived classes
public abstract decimal CalculateSalary();
// Concrete method
public virtual void DisplayInfo()
{
Console.WriteLine($"Employee: {Name}, ID: {EmployeeId}");
}
}
public class FullTimeEmployee : Employee
{
public decimal MonthlySalary { get; set; }
public override decimal CalculateSalary()
{
return MonthlySalary;
}
public override void DisplayInfo()
{
base.DisplayInfo();
Console.WriteLine($"Type: Full-time, Salary: ${MonthlySalary}/month");
}
}
public class PartTimeEmployee : Employee
{
public decimal HourlyRate { get; set; }
public int HoursWorked { get; set; }
public override decimal CalculateSalary()
{
return HourlyRate * HoursWorked;
}
public override void DisplayInfo()
{
base.DisplayInfo();
Console.WriteLine($"Type: Part-time, Rate: ${HourlyRate}/hour, Hours: {HoursWorked}");
}
}
// Usage
List<Employee> employees = new List<Employee>
{
new FullTimeEmployee { Name = "John", EmployeeId = "FT001", MonthlySalary = 5000 },
new PartTimeEmployee { Name = "Jane", EmployeeId = "PT001", HourlyRate = 25, HoursWorked = 80 }
};
foreach (Employee emp in employees)
{
emp.DisplayInfo();
Console.WriteLine($"Monthly Pay: ${emp.CalculateSalary()}");
Console.WriteLine();
}
6. Complete Real-World Example
Let's combine all OOP concepts in a comprehensive example:
csharp
using System;
using System.Collections.Generic;
namespace OOPExample
{
// Base class
public abstract class Product
{
// Encapsulated fields
private string _name;
private decimal _price;
// Properties with validation
public string ProductId { get; set; }
public string Name
{
get { return _name; }
set
{
if (!string.IsNullOrWhiteSpace(value))
_name = value;
else
throw new ArgumentException("Name cannot be empty");
}
}
public decimal Price
{
get { return _price; }
set
{
if (value >= 0)
_price = value;
else
throw new ArgumentException("Price cannot be negative");
}
}
// Constructor
protected Product(string productId, string name, decimal price)
{
ProductId = productId;
Name = name;
Price = price;
}
// Abstract method
public abstract void DisplayInfo();
// Virtual method
public virtual decimal CalculateDiscount(int quantity)
{
return 0; // No discount by default
}
}
// Derived class 1
public class Book : Product
{
public string Author { get; set; }
public string ISBN { get; set; }
public Book(string productId, string name, decimal price, string author, string isbn)
: base(productId, name, price)
{
Author = author;
ISBN = isbn;
}
// Override abstract method
public override void DisplayInfo()
{
Console.WriteLine($"Book: {Name} by {Author}");
Console.WriteLine($"ISBN: {ISBN}, Price: ${Price}");
}
// Override virtual method
public override decimal CalculateDiscount(int quantity)
{
if (quantity >= 5)
return Price * quantity * 0.1m; // 10% discount for 5+ books
return 0;
}
}
// Derived class 2
public class Electronics : Product
{
public string Brand { get; set; }
public int WarrantyMonths { get; set; }
public Electronics(string productId, string name, decimal price, string brand, int warranty)
: base(productId, name, price)
{
Brand = brand;
WarrantyMonths = warranty;
}
// Override abstract method
public override void DisplayInfo()
{
Console.WriteLine($"Electronics: {Name} by {Brand}");
Console.WriteLine($"Warranty: {WarrantyMonths} months, Price: ${Price}");
}
// Override virtual method
public override decimal CalculateDiscount(int quantity)
{
// Electronics get flat discount
return quantity >= 2 ? 50 : 0;
}
}
class Program
{
static void Main()
{
// Polymorphic collection
List<Product> products = new List<Product>
{
new Book("B001", "C# Programming", 49.99m, "John Doe", "978-0123456789"),
new Book("B002", "ASP.NET Core", 59.99m, "Jane Smith", "978-9876543210"),
new Electronics("E001", "Laptop", 999.99m, "Dell", 24),
new Electronics("E002", "Smartphone", 699.99m, "Samsung", 12)
};
// Demonstrate polymorphism
foreach (Product product in products)
{
product.DisplayInfo();
decimal discount = product.CalculateDiscount(3);
if (discount > 0)
Console.WriteLine($"Discount for 3 items: ${discount}");
Console.WriteLine();
}
// Demonstrate specific type handling
foreach (Product product in products)
{
if (product is Book book)
{
Console.WriteLine($"Book specific: Author is {book.Author}");
}
else if (product is Electronics electronics)
{
Console.WriteLine($"Electronics specific: Brand is {electronics.Brand}");
}
}
}
}
}
Key OOP Principles Summary
-
Encapsulation: Hide internal state and require all interaction through methods/properties
-
Inheritance: Create new classes based on existing ones to promote code reuse
-
Polymorphism: Allow objects of different types to be treated as objects of a common type
-
Abstraction: Hide complex implementation details and show only essential features
These OOP concepts form the foundation of modern C# development and are essential for building maintainable, scalable, and organized applications.
Comments (0)
No comments yet. Be the first to comment!