Skip to main content

Command Palette

Search for a command to run...

The Ultimate Guide to Sealed Classes in C#

Published
5 min read
The Ultimate Guide to Sealed Classes in C#
T
I focus on clean architecture, performance optimization, and designing systems that are maintainable and resilient.

The Ultimate Guide to Sealed Classes in C#

🎥 Watch the original video on YouTube: Click here to watch


The Ultimate Guide to Sealed Classes in C

When building robust object-oriented applications in C#, controlling inheritance hierarchies is crucial for maintaining code integrity and preventing unintended modifications. One powerful tool at your disposal is the sealed class—a feature that allows you to explicitly prevent a class from being inherited. In this comprehensive guide, we'll explore sealed classes in depth, understand their use cases, and learn how they complement other class types in C#.

Understanding Class Types in C

Before diving into sealed classes specifically, it's important to understand the broader landscape of class types in C#. Classes in C# can be categorized into several types:

  • Abstract Classes: Cannot be instantiated directly but can be inherited; designed to serve as a base for derived classes
  • Concrete Classes: Fully implemented classes that can be instantiated directly
  • Sealed Classes: Cannot be inherited; designed to prevent further derivation
  • Partial Classes: Split across multiple files for better code organization
  • Static Classes: Contain only static members and cannot be instantiated

Each class type serves a distinct purpose in your application architecture.

What Are Sealed Classes?

A sealed class is a class that cannot be inherited from by other classes. When you mark a class with the sealed keyword, you explicitly prevent any derived classes from extending its functionality. This is the opposite approach compared to abstract classes, which are specifically designed to be inherited.

The Sealed Keyword

The syntax for creating a sealed class is straightforward:

public sealed class Manager
{
    public string Name { get; set; }
    public decimal Salary { get; set; }

    public virtual void DisplayDetails()
    {
        Console.WriteLine($"Manager: {Name}, Salary: {Salary}");
    }
}

Once you mark a class as sealed, attempting to inherit from it will result in a compilation error:

// This will cause a compiler error
public class SeniorManager : Manager
{
    // Cannot derive from sealed type 'Manager'
}

Why Use Sealed Classes?

Preventing Unintended Inheritance

The primary reason to use sealed classes is to prevent other developers from inheriting from your class when inheritance is not intended. This is particularly useful when:

  • Your class is designed to be used as-is without modification
  • The internal implementation details should not be extended or overridden
  • You want to maintain strict control over the class's behavior
  • The class represents a complete, self-contained concept

Performance Considerations

Sealed classes can provide minor performance benefits because the compiler and runtime can skip virtual method dispatch optimization checks when the type is known to be sealed. This optimization opportunity is typically negligible in most applications but can contribute to performance in high-throughput scenarios.

Sealed Methods vs. Sealed Classes

While sealing an entire class is one approach, C# also allows you to seal individual methods within a class hierarchy. This is where the sealed keyword becomes particularly nuanced.

Sealing Virtual Methods

When a derived class overrides a virtual method and marks it as sealed, it prevents further derived classes from overriding that same method:

public class Employee
{
    public virtual void PrintDetails()
    {
        Console.WriteLine("Employee Details");
    }
}

public class Manager : Employee
{
    public sealed override void PrintDetails()
    {
        Console.WriteLine("Manager Details");
        // This method cannot be overridden in derived classes
    }
}

public class SeniorManager : Manager
{
    // Compilation error: Cannot override sealed member
    // public override void PrintDetails() { }
}

This approach is useful when you want to allow inheritance but prevent further modification of specific methods. For example, you might want derived classes to inherit your implementation and behavior for one method, but allow them to override other methods.

Practical Examples

Example 1: Sealed Printer Class

Consider a printer system where you have a base Printer class with virtual methods, but you want a LaserJetPrinter class that cannot be further derived:

public class Printer
{
    public virtual void Display()
    {
        Console.WriteLine("Printer Display");
    }

    public virtual void Print()
    {
        Console.WriteLine("Printer Print");
    }
}

public sealed class LaserJetPrinter : Printer
{
    public override void Display()
    {
        Console.WriteLine("LaserJet Display");
    }

    public override void Print()
    {
        Console.WriteLine("LaserJet Print - High Quality");
    }
}

// This will cause an error
// public class AdvancedLaserJet : LaserJetPrinter { }

Example 2: Preventing Method Override After Sealing

public class Printer
{
    public virtual void Display()
    {
        Console.WriteLine("Printer Display");
    }

    public virtual void Print()
    {
        Console.WriteLine("Printer Print");
    }
}

public class LaserJetPrinter : Printer
{
    // Display method is sealed - cannot be overridden further
    public sealed override void Display()
    {
        Console.WriteLine("LaserJet Display - Optimized");
    }

    // Print method can still be overridden
    public override void Print()
    {
        Console.WriteLine("LaserJet Print");
    }
}

public class ColorLaserJet : LaserJetPrinter
{
    // This is allowed because Print is not sealed
    public override void Print()
    {
        Console.WriteLine("Color LaserJet Print - Full Color");
    }

    // This would cause an error because Display is sealed
    // public override void Display() { }
}

Key Takeaways

  • Sealed classes prevent inheritance entirely and cannot be used as base classes
  • Sealed methods prevent further overriding in derived classes but allow the class itself to be inherited
  • Use sealed classes when you have a complete, self-contained implementation that shouldn't be extended
  • Use sealed methods to lock in specific behavior while allowing other methods to be overridden
  • Sealed classes are the opposite of abstract classes in their design philosophy
  • The primary benefit is enforcing design intent and preventing unintended modifications to class behavior
  • There are minimal performance benefits to using sealed classes in typical applications

Conclusion

Sealed classes are a valuable tool in the C# developer's toolkit for enforcing architectural decisions and preventing unintended inheritance. Whether you're building a library, framework, or large-scale application, understanding when and how to use the sealed keyword helps you create more maintainable, predictable code. By combining sealed classes and sealed methods strategically, you can strike the right balance between extensibility and control, ensuring that your code's behavior remains consistent and intentional throughout your application's inheritance hierarchy.