Skip to content

Instantly share code, notes, and snippets.

@vasilkosturski
Last active July 7, 2020 12:21
Show Gist options
  • Save vasilkosturski/55e6297175b5070df2ced49b07d880b5 to your computer and use it in GitHub Desktop.
Save vasilkosturski/55e6297175b5070df2ced49b07d880b5 to your computer and use it in GitHub Desktop.
clash-of-styles-double-dispatch
using System;
namespace DoubleDispatch
{
class Program
{
static void Main(string[] args)
{
var expression = new Addition(
new MyInt(3),
new Addition(new MyRational(2, 3), new MyInt(5)));
var asString = expression.Stringify();
var result = expression.Eval();
Console.WriteLine($"{asString} = {result.Stringify()}"); // 3 + 2/3 + 5 = 26/3
}
}
public interface IExpression
{
IValue Eval();
string Stringify();
}
public interface IValue : IExpression
{
IValue AddValue(IValue operand);
IValue AddInt(MyInt operand);
IValue AddRational(MyRational operand);
}
public class MyInt : IValue
{
public int Val { get; }
public MyInt(int val)
{
Val = val;
}
public IValue Eval() => this;
public string Stringify() => Val.ToString();
public IValue AddValue(IValue operand) => operand.AddInt(this);
public IValue AddInt(MyInt operand) => new MyInt(Val + operand.Val);
public IValue AddRational(MyRational operand)
=> new MyRational(operand.Numerator + operand.Denominator * Val, operand.Denominator);
}
public class MyRational : IValue
{
public int Numerator { get; }
public int Denominator { get; }
public MyRational(int numerator, int denominator)
{
Numerator = numerator;
Denominator = denominator;
}
public IValue Eval() => this;
public string Stringify() => $"{Numerator}/{Denominator}";
public IValue AddValue(IValue operand)
=> operand.AddRational(this);
public IValue AddInt(MyInt operand)
=> operand.AddRational(this);
public IValue AddRational(MyRational operand)
{
return new MyRational(
Numerator * operand.Denominator + operand.Numerator * Denominator,
Denominator * operand.Denominator);
}
}
public class Addition : IExpression
{
private readonly IExpression _operand1;
private readonly IExpression _operand2;
public Addition(IExpression operand1, IExpression operand2)
{
_operand1 = operand1;
_operand2 = operand2;
}
public IValue Eval() => _operand1.Eval().AddValue(_operand2.Eval());
public string Stringify() => $"{_operand1.Stringify()} + {_operand2.Stringify()}";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment