C# Mastery

Polymorphism vs Composition (The Architect's Dilemma)

1 Views Updated 5/4/2026

Polymorphism vs Composition

Every senior developer eventually faces the same wall: their inheritance hierarchy has become a tangled nightmare. While Polymorphism (Inheritance) is a pillar of OOP, modern software engineering increasingly favors Composition for its flexibility and testability.

1. The Trap of Deep Inheritance

Imagine a hierarchy: Vehicle -> Car -> ElectricCar. What if you suddenly need a HybridCar? Or a FlyingCar? You end up with "The Diamond Problem" or redundant code in multiple branches.

2. Composition: The "Has-A" Approach

Instead of inheriting behavior, you inject it. A car doesn't have to be an ElectricVehicle; it can simply have an IEngine implementation.

public class Car 
{
    private readonly IEngine _engine;
    public Car(IEngine engine) => _engine = engine;

    public void Start() => _engine.Ignite();
}

// Now we can easily swap behaviors without changing the Car class!
var tesla = new Car(new ElectricEngine());
var ford = new Car(new GasEngine());

3. Polymorphism: The "Is-A" Approach

Use inheritance ONLY when there is a true, unchanging hierarchical relationship. Polymorphism allows you to treat specialized objects as their base types, enabling powerful generic logic.

public abstract class Shape { public abstract double Area(); }

// We can calculate area for a list of ANY shapes!
public void PrintAreas(List<Shape> shapes) 
{
    foreach(var s in shapes) Console.WriteLine(s.Area());
}

4. Interview Mastery

Q: "What is the Liskov Substitution Principle (LSP) in the context of Polymorphism?"

Architect Answer: "The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of its subclasses without breaking the application. A classic violation is the 'Square-Rectangle' problem. If a `Square` inherits from `Rectangle`, but you override `SetWidth` to also change the `Height`, a method expecting a standard Rectangle will behave incorrectly. If you find yourself throwing `NotImplementedException` inside a subclass method, you are likely violating LSP and should probably switch to Composition instead."

C# Mastery
1. Modern C# & Framework Fundamentals
Introduction to the .NET Ecosystem & Runtime (JIT, CLR) C# 12/13 Top-Level Statements & Global Usings Variables, Data Types, and Value vs Reference Deep Dive Mastering Nullable Reference Types & Null Safety The Magic of Strings (Interpolation, Verbatim, and Immutability)
2. Control Flow & Logical Structures
Advanced Pattern Matching (Switch Expressions) The Precision of Numbers: Checked vs Unchecked Math Iterators: Foreach, Yield Return, and Deferred Execution Defensive Programming: Guard Clauses and Exception Mastery
3. Object-Oriented Mastery
Classes vs Structs vs Records (Which to use when?) Mastering Primary Constructors & Object Initializers Interface Architectures: Default Implementations & Segregation Polymorphism vs Composition (The Architect's Dilemma) Partial Classes, Extension Methods, and Static Classes
4. Functional C# & Collections
Delegates, Func, Action, and Predicates Lambda Expressions & The Evolution of Linq Dynamic Array Management: List<T>, Dictionary, and HashSet Custom Collections & Yielding Data streams
5. Asynchronous & Parallel Programming
Async/Await Deep Dive: Task Lifecycle & Thread Safety Synchronization Context & Avoiding Deadlocks Parallel.ForEach vs PLINQ vs Tasks CancellationToken Mastery: Surgically Aborting Operations
6. Advanced Engineering & High Performance
Generics & Constraints: Building Type-Safe Libraries Reflection and Attributes: Reading Metadata at Runtime Dependency Injection Internals (ServiceCollection from scratch) High-Performance Memory: Span<T> and ReadOnlySpan<T> Garbage Collection Segments & LOH Internals Managing Unmanaged Resources: IDisposable & Finalizers Introduction to Source Generators & Interceptors C# Interview Masterclass: Architect-Level Explanations