public TResult Match <TResult>(OnCircle <TResult> circle,
                                       OnRectangle <TResult> rectangle)
        {
            switch (Tag)
            {
            case ShapeCase.Circle:
                return(circle(Radius));

            case ShapeCase.Rectangle:
                return(rectangle(Height, Width));

            default:
                throw new InvalidOperationException();
            }
        }
        public TResult Match <TResult>(OnCircle <TResult> circle,
                                       OnEquilateralTriangle <TResult> equilateralTriangle,
                                       OnSquare <TResult> onSquare,
                                       OnRectangle <TResult> rectangle)
        {
            switch (Tag)
            {
            case ShapeCase.Circle:
                return(circle(Radius));

            case ShapeCase.EquilateralTriangle:
                return(equilateralTriangle(SideLen));

            case ShapeCase.Square:
                return(onSquare(SideLen));

            case ShapeCase.Rectangle:
                return(rectangle(Height, Width));

            default:
                throw new InvalidOperationException();
            }
        }