Skip to main content

.NET Method Overriding

Method overriding is a fundamental concept in object-oriented programming that allows a derived class to provide a specific implementation of a method that is already defined in its base class. This is one of the key mechanisms that enable polymorphism in C# and .NET.

Introduction to Method Overriding

In object-oriented programming, classes can inherit properties and behaviors from other classes. Sometimes, you need a derived class to change or extend the behavior defined in the base class. Method overriding enables you to redefine a method in a derived class that has already been defined in the base class.

The key points about method overriding include:

  • It implements runtime polymorphism
  • It requires inheritance (a parent-child class relationship)
  • The method in the base class must be declared as virtual
  • The method in the derived class must use the override keyword

Method Overriding vs Method Hiding vs Method Overloading

Before diving deeper, let's clarify the differences between these similar concepts:

ConceptDescription
Method OverridingRedefines a method in a derived class that is already defined in the base class (using virtual and override keywords)
Method HidingSimilar to overriding, but uses the new keyword instead of override to hide the base implementation
Method OverloadingMultiple methods with the same name but different parameters in the same class

How Method Overriding Works in C#

To override a method in C#:

  1. The base class method must be declared with the virtual keyword
  2. The derived class method must use the override keyword
  3. Both methods must have the same name, return type, and parameters

Let's look at a basic example:

csharp
public class Shape
{
public virtual void Draw()
{
Console.WriteLine("Drawing a shape");
}
}

public class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}

public class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a rectangle");
}
}

When we use these classes:

csharp
// Example usage
Shape shape = new Shape();
shape.Draw(); // Output: "Drawing a shape"

Shape circle = new Circle();
circle.Draw(); // Output: "Drawing a circle"

Shape rectangle = new Rectangle();
rectangle.Draw(); // Output: "Drawing a rectangle"

The virtual Keyword

The virtual keyword in the base class indicates that a method can be overridden in derived classes. Without this keyword, derived classes cannot override the method.

The override Keyword

The override keyword in the derived class indicates that this method provides a new implementation of a virtual method defined in the base class.

Accessing the Base Class Method

Sometimes, you might want to extend the base class functionality rather than completely replacing it. The base keyword allows you to call the base class method from the derived class:

csharp
public class Circle : Shape
{
public override void Draw()
{
base.Draw(); // Call the base class implementation first
Console.WriteLine("Drawing a circle with radius");
}
}

Output when calling circle.Draw():

Drawing a shape
Drawing a circle with radius

Abstract Methods and Method Overriding

Abstract methods are closely related to method overriding. An abstract method has no implementation in the base class and must be overridden in derived classes.

csharp
public abstract class Shape
{
public abstract void Draw(); // No implementation, must be overridden

public void DisplayArea()
{
Console.WriteLine("Displaying area calculation");
}
}

public class Circle : Shape
{
public override void Draw() // Must implement this method
{
Console.WriteLine("Drawing a circle");
}
}

Real-World Example: Banking System

Let's explore a more practical example of method overriding in a banking system:

csharp
public class BankAccount
{
public string AccountNumber { get; set; }
protected decimal balance;

public BankAccount(string accountNumber, decimal initialBalance)
{
AccountNumber = accountNumber;
balance = initialBalance;
}

public virtual string GetAccountInfo()
{
return $"Account Number: {AccountNumber}, Balance: ${balance}";
}

public virtual void Deposit(decimal amount)
{
if (amount > 0)
{
balance += amount;
Console.WriteLine($"Deposited ${amount}. New balance: ${balance}");
}
}

public virtual bool Withdraw(decimal amount)
{
if (amount <= balance && amount > 0)
{
balance -= amount;
Console.WriteLine($"Withdrew ${amount}. New balance: ${balance}");
return true;
}
Console.WriteLine("Insufficient funds or invalid amount");
return false;
}
}

public class SavingsAccount : BankAccount
{
public decimal InterestRate { get; private set; }

public SavingsAccount(string accountNumber, decimal initialBalance, decimal interestRate)
: base(accountNumber, initialBalance)
{
InterestRate = interestRate;
}

public override string GetAccountInfo()
{
return $"{base.GetAccountInfo()}, Interest Rate: {InterestRate:P}";
}

public void AddInterest()
{
decimal interest = balance * InterestRate;
balance += interest;
Console.WriteLine($"Added ${interest} interest. New balance: ${balance}");
}
}

public class CheckingAccount : BankAccount
{
public decimal OverdraftLimit { get; private set; }

public CheckingAccount(string accountNumber, decimal initialBalance, decimal overdraftLimit)
: base(accountNumber, initialBalance)
{
OverdraftLimit = overdraftLimit;
}

public override string GetAccountInfo()
{
return $"{base.GetAccountInfo()}, Overdraft Limit: ${OverdraftLimit}";
}

public override bool Withdraw(decimal amount)
{
if (amount > 0 && amount <= (balance + OverdraftLimit))
{
balance -= amount;
Console.WriteLine($"Withdrew ${amount}. New balance: ${balance}");

if (balance < 0)
{
Console.WriteLine($"Warning: Account is overdrawn by ${Math.Abs(balance)}");
}

return true;
}

Console.WriteLine("Insufficient funds (exceeds overdraft limit) or invalid amount");
return false;
}
}

Using these classes:

csharp
// Create different account types
SavingsAccount savings = new SavingsAccount("SA-1234", 1000, 0.05m);
CheckingAccount checking = new CheckingAccount("CA-5678", 500, 200);

// Test method overriding with polymorphism
BankAccount account1 = savings;
BankAccount account2 = checking;

Console.WriteLine(account1.GetAccountInfo());
// Output: Account Number: SA-1234, Balance: $1000, Interest Rate: 5.00%

Console.WriteLine(account2.GetAccountInfo());
// Output: Account Number: CA-5678, Balance: $500, Overdraft Limit: $200

// Test the overridden Withdraw method
account1.Withdraw(200); // Uses base implementation
// Output: Withdrew $200. New balance: $800

account2.Withdraw(600); // Uses overridden implementation
// Output: Withdrew $600. New balance: $-100
// Warning: Account is overdrawn by $100

Best Practices for Method Overriding

  1. Clear Purpose: Only override methods when you need to change or extend behavior
  2. Maintain Contracts: The overridden method should follow the same contract (expected behavior) as the base method
  3. Use base: Call the base implementation when extending functionality rather than completely replacing it
  4. Avoid Deep Hierarchies: Excessive inheritance can make code hard to understand
  5. Documentation: Clearly document the differences in behavior when overriding methods

When to Use Method Overriding

Method overriding is appropriate in the following scenarios:

  • When a derived class needs to modify behavior inherited from the base class
  • When implementing polymorphic behavior
  • When working with an abstract class that requires implementation of abstract methods
  • When extending functionality of a base class method

Common Pitfalls and Solutions

1. Forgetting the virtual Keyword

If you forget to mark a method as virtual in the base class:

csharp
public class Base
{
public void Method() // Missing 'virtual' keyword
{
Console.WriteLine("Base Method");
}
}

public class Derived : Base
{
public override void Method() // Compilation error
{
Console.WriteLine("Derived Method");
}
}

This will cause a compilation error because the method in the base class is not marked as virtual.

2. Forgetting the override Keyword

If you forget the override keyword, C# will interpret it as method hiding:

csharp
public class Base
{
public virtual void Method()
{
Console.WriteLine("Base Method");
}
}

public class Derived : Base
{
public void Method() // Missing 'override' keyword
{
Console.WriteLine("Derived Method");
}
}

The compiler will warn you that this hides the base method, and you should use either new or override.

Summary

Method overriding is a powerful feature in .NET that allows derived classes to provide specific implementations of methods defined in the base class. Key points to remember:

  • Use the virtual keyword in the base class to allow overriding
  • Use the override keyword in the derived class to override a method
  • Method overriding enables polymorphism, a core OOP principle
  • The base keyword allows you to call the base class implementation
  • Abstract methods must be overridden in non-abstract derived classes
  • Method overriding is different from method hiding and method overloading

By mastering method overriding, you'll be able to write more flexible and maintainable object-oriented code in C# and .NET.

Exercises

  1. Create a Vehicle base class with a virtual method called CalculateFuelEfficiency(). Then create Car and Motorcycle derived classes that override this method with their own implementations.

  2. Extend the banking example above by adding a BusinessAccount class that overrides the Withdraw method to include a transaction fee.

  3. Create an abstract Employee class with an abstract CalculatePay() method, then implement concrete derived classes for different employee types.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)