using System.Collections.Generic;
internal interface IShape
T Accept<T>(IShapeVisitor<T> calculator);
internal interface IShapeVisitor<T>
public static void Main(string[] args)
var shapes = new List<IShape>()
var areaCalculator = new AreaCalculator();
foreach (var shape in shapes)
var area = shape.Accept(areaCalculator);
internal sealed class AreaCalculator : IShapeVisitor<double>
public double Visit(Circle circle)
return System.Math.PI * circle.R * circle.R;
public double Visit(Square square)
return square.A * square.A;
internal sealed class Circle : IShape
public double R { get { return _r; } }
public T Accept<T>(IShapeVisitor<T> calculator)
return calculator.Visit(this);
internal sealed class Square : IShape
private readonly double _a;
public double A { get { return _a; } }
public T Accept<T>(IShapeVisitor<T> calculator)
return calculator.Visit(this);