public static void Main()
INumber zero = Number.Zero;
INumber two = Number.One.Increment();
Console.WriteLine(zero.Increment());
Console.WriteLine(two.Decrement());
INumber Add(INumber number);
INumber Subtract(INumber number);
public abstract class Number : INumber
public static INumber Zero { get; } = new ZeroNumber();
public static INumber One { get; } = new OneNumber();
public int Value { get; }
protected Number(int value) => this.Value = value;
protected Number(INumber number)
: this(number?.Value ?? throw new ArgumentNullException(nameof(number)))
public override string ToString() => this.Value.ToString();
public INumber Negate() => new OtherNumber(-this.Value);
public INumber Increment()
return new OtherNumber(++value);
public INumber Decrement()
return new OtherNumber(--value);
public INumber Add(INumber number) => new OtherNumber(this.Value + number.Value);
public INumber Subtract(INumber number) => this.Add(number.Negate());
private sealed class ZeroNumber : Number
public ZeroNumber(): base(0) { }
private sealed class OneNumber : Number
public OneNumber(): base(Zero.Increment()) { }
private sealed class OtherNumber : Number
public OtherNumber(int value): base(value) { }