Menu

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:

  1. Compile-time polymorphism (Method overloading)

  2. 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

  1. Encapsulation: Hide internal state and require all interaction through methods/properties

  2. Inheritance: Create new classes based on existing ones to promote code reuse

  3. Polymorphism: Allow objects of different types to be treated as objects of a common type

  4. 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!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?