Lesson 16 — Many Forms

Polymorphism

C# polymorphism works via virtual/override and is enhanced by pattern matching — making type-based dispatch concise and safe.

CSHARP — Polymorphism
Person[] group = {
    new Learner("Thandi",  21, "C#",   74.5),
    new Learner("Sipho",   24, "Java", 81.0),
    new Facilitator("Ms Dube", 34, "Software Dev"),
    new Learner("Lerato",  20, "SQL",  68.0)
};

// One loop — Java calls the right override for each object:
foreach (var person in group)
    person.Introduce();

Pattern Matching

C# pattern matching is more powerful than Java's instanceof — it can match types, conditions, and values simultaneously.

CSHARP — Pattern matching
foreach (var person in group) {
    // is-pattern: check type AND cast in one step:
    if (person is Learner l)
        Console.WriteLine($"  Learner {l.Name}: {l.Course} | {l.Mark}%");
    else if (person is Facilitator f)
        Console.WriteLine($"  Facilitator {f.Name}: {f.Specialisation}");
}

// Switch expression with type patterns:
static string Describe(Person p) => p switch {
    Learner l when l.Mark >= 80 => $"{l.Name} — Distinction in {l.Course}",
    Learner l                   => $"{l.Name} — studying {l.Course}",
    Facilitator f               => $"{f.Name} — facilitator",
    _                           => "Unknown person type"
};

foreach (var p in group)
    Console.WriteLine(Describe(p));

Practice Task

Your Turn

Create a Shape hierarchy (Circle, Rectangle, Triangle all extending abstract Shape). Override ToString() on each. Store in Shape[]. Use a switch expression with type patterns to print the area of each with two decimal places. Calculate and print the total combined area.

Common Mistakes

  • Forgetting virtual on the parent method.
  • as without null check — returns null if cast fails, then NullReferenceException on next access.
  • Direct cast without type check — throws InvalidCastException.
  • Overusing pattern matching when a virtual method would be cleaner.

Professional Tip

Pattern matching is best for external dispatch — when you cannot add a virtual method to the type. For types you own, prefer virtual methods and polymorphism.

Mini Quiz

What does 'if (p is Learner l)' do in C#?