A base-class array can hold different derived objects and call virtual methods.

polymorphism Polymorphism uses the derived method that matches the actual object.

Polymorphic Arrays

separator
PolymorphicArrays.cs
Replay: real traced execution (multi-file project)
using System;

class Shape
{
    public virtual string Name()
    {
        return "shape";
    }
}

class Circle : Shape
{
    public override string Name()
    {
        return "circle";
    }
}

class Square : Shape
{
    public override string Name()
    {
        return "square";
    }
}

class Program
{
    static void Main()
    {
        string separator = ",";
        Shape[] shapes = { new Circle(), new Square() };
        string summary = "";

        foreach (Shape shape in shapes)
        {
            if (summary.Length > 0)
            {
                summary += separator;
            }

            summary += shape.Name();
        }

        Console.WriteLine($"separator={separator}");
        Console.WriteLine($"summary={summary}");
    }
}
using System;

class Shape
{
    public virtual string Name()
    {
        return "shape";
    }
}

class Circle : Shape
{
    public override string Name()
    {
        return "circle";
    }
}

class Square : Shape
{
    public override string Name()
    {
        return "square";
    }
}

class Program
{
    static void Main()
    {
        string separator = " | ";
        Shape[] shapes = { new Circle(), new Square() };
        string summary = "";

        foreach (Shape shape in shapes)
        {
            if (summary.Length > 0)
            {
                summary += separator;
            }

            summary += shape.Name();
        }

        Console.WriteLine($"separator={separator}");
        Console.WriteLine($"summary={summary}");
    }
}
using System;

class Shape
{
    public virtual string Name()
    {
        return "shape";
    }
}

class Circle : Shape
{
    public override string Name()
    {
        return "circle";
    }
}

class Square : Shape
{
    public override string Name()
    {
        return "square";
    }
}

class Program
{
    static void Main()
    {
        string separator = "/";
        Shape[] shapes = { new Circle(), new Square() };
        string summary = "";

        foreach (Shape shape in shapes)
        {
            if (summary.Length > 0)
            {
                summary += separator;
            }

            summary += shape.Name();
        }

        Console.WriteLine($"separator={separator}");
        Console.WriteLine($"summary={summary}");
    }
}
  1. separator ← ,, shapes ← Shape[], summary ← (empty)

    28{29    static void Main()30    {31        string separator→ , = ","; //@separator=" | ", "/"32        Shape[] shapes→ Shape[] = { new Circle(), new Square() };33        string summary→ (empty) = "";
  2. foreach (Shape shape in shapes)

    pass 1 of 2
    35foreach (Shape shapeCircle in shapesShape[])36{37    if (summary.Length > 0)38    {39        summary += separator;40    }4142    summary += shapeCircle.Name();43}
  3. summary ← circle

    42    summary→ circle += shapeCircle.Name();43}
  4. foreach (Shape shape in shapes)

    pass 2 of 2
    35foreach (Shape shapeSquare in shapesShape[])36{37    if (summary.Length > 0)
  5. summary ← circle,

    36{37    if (summary.Length6 > 0)38    {39        summary→ circle, += separator,;40    }
  6. summary += shape.Name();

    42    summary += shapeSquare.Name();43}
  7. summary ← circle,square

    42    summary→ circle,square += shapeSquare.Name();43}
  8. Console.WriteLine($"separator={separator}");

    45    Console.WriteLine($"separator={separator,}");46    Console.WriteLine($"summary={summarycircle,square}");47}
    outputseparator=,
    summary=circle,square
  1. separator ← | , shapes ← Shape[], summary ← (empty)

    28{29    static void Main()30    {31        string separator→  |  = " | ";32        Shape[] shapes→ Shape[] = { new Circle(), new Square() };33        string summary→ (empty) = "";
  2. foreach (Shape shape in shapes)

    pass 1 of 2
    35foreach (Shape shapeCircle in shapesShape[])36{37    if (summary.Length > 0)38    {39        summary += separator;40    }4142    summary += shapeCircle.Name();43}
  3. summary ← circle

    42    summary→ circle += shapeCircle.Name();43}
  4. foreach (Shape shape in shapes)

    pass 2 of 2
    35foreach (Shape shapeSquare in shapesShape[])36{37    if (summary.Length > 0)
  5. summary ← circle |

    36{37    if (summary.Length6 > 0)38    {39        summary→ circle |  += separator | ;40    }
  6. summary += shape.Name();

    42    summary += shapeSquare.Name();43}
  7. summary ← circle | square

    42    summary→ circle | square += shapeSquare.Name();43}
  8. Console.WriteLine($"separator={separator}");

    45    Console.WriteLine($"separator={separator | }");46    Console.WriteLine($"summary={summarycircle | square}");47}
    outputseparator= |
    summary=circle | square
  1. separator ← /, shapes ← Shape[], summary ← (empty)

    28{29    static void Main()30    {31        string separator→ / = "/";32        Shape[] shapes→ Shape[] = { new Circle(), new Square() };33        string summary→ (empty) = "";
  2. foreach (Shape shape in shapes)

    pass 1 of 2
    35foreach (Shape shapeCircle in shapesShape[])36{37    if (summary.Length > 0)38    {39        summary += separator;40    }4142    summary += shapeCircle.Name();43}
  3. summary ← circle

    42    summary→ circle += shapeCircle.Name();43}
  4. foreach (Shape shape in shapes)

    pass 2 of 2
    35foreach (Shape shapeSquare in shapesShape[])36{37    if (summary.Length > 0)
  5. summary ← circle/

    36{37    if (summary.Length6 > 0)38    {39        summary→ circle/ += separator/;40    }
  6. summary += shape.Name();

    42    summary += shapeSquare.Name();43}
  7. summary ← circle/square

    42    summary→ circle/square += shapeSquare.Name();43}
  8. Console.WriteLine($"separator={separator}");

    45    Console.WriteLine($"separator={separator/}");46    Console.WriteLine($"summary={summarycircle/square}");47}
    outputseparator=/
    summary=circle/square