using System; namespace Factorial { class Program { static void Main(string[] args) { Factorial f = new Factorial(new intFact(5)); Console.WriteLine(f.Value); } } struct intFact : IFactoriable { public int n; public intFact(int num) { n = num; } public bool isZero() { return n == 0; } public bool isBelowZero() { return n < 0; } public intFact Step() { return new intFact(n - 1); } public intFact Multiply(intFact iF) { return new intFact(n * iF.n); } public intFact getNeutralElement() { return new intFact(1); } public override string ToString() { return n.ToString(); } } [Serializable] class Factorial where T : IFactoriable { T p; public T Value { get; private set; } public T Param { get { return p; } set { if (value.isBelowZero()) throw new ArgumentOutOfRangeException("n or Param"); Value = fact(value); p = value; } } public Factorial(T n) { Param = n; } T fact(T n) { if (n.isZero()) return n.getNeutralElement(); return n.Multiply(fact(n.Step())); } } interface IFactoriable { bool isZero(); bool isBelowZero(); T Step(); T getNeutralElement(); T Multiply(T t); } }