using System;

// Standalone illustration of the dispatch pattern, not generated PPJ output.
public class BaseRule
{
    public int Calculate() { return 10; }
    public int EvaluateDirect() { return Calculate(); }
    public int EvaluateLate() { return __Calculate(); }
    public virtual int __Calculate() { return Calculate(); }
}

public class DerivedRule : BaseRule
{
    public new int Calculate() { return 20; }
    public override int __Calculate() { return Calculate(); }
}

public static class LateBindDemo
{
    public static void Main()
    {
        var baseObject = new BaseRule();
        var derivedObject = new DerivedRule();
        BaseRule baseReference = derivedObject;
        Check("base ordinary", baseObject.EvaluateDirect(), 10);
        Check("base late", baseObject.EvaluateLate(), 10);
        Check("derived inherited ordinary", derivedObject.EvaluateDirect(), 10);
        Check("derived late", derivedObject.EvaluateLate(), 20);
        Check("base reference late", baseReference.EvaluateLate(), 20);
        Check("derived direct member", derivedObject.Calculate(), 20);
        Check("base reference direct member", baseReference.Calculate(), 10);
        Console.WriteLine("PASS: all 7 dispatch checks");
    }

    private static void Check(string name, int actual, int expected)
    {
        if (actual != expected) throw new InvalidOperationException(name);
        Console.WriteLine(name + ": " + actual);
    }
}
