Если вы можете изменить реализацию Context для поддержки универсальных типов (например, Pop<int>
вместо PopINT()
), вы можете использовать делегаты, чтобы упростить реализацию.
Дополнительно:
var addInt = new MathInstruction<int>((a, b) => a + b));
var addDouble = new MathInstruction<double>((a, b) => a + b));
var addDecimal = new MathInstruction<decimal>((a, b) => a + b));
Вычитание
var subtractInt = new MathInstruction<int>((a, b) => a - b));
var subtractDouble = new MathInstruction<double>((a, b) => a - b));
var subtractDecimal = new MathInstruction<decimal>((a, b) => a - b));
Отдел:
var divideIntAsDouble = new MathInstruction<int, double>((a, b) => a / b));
var divideDouble = new MathInstruction<double>((a, b) => a / b));
var divideDecimal = new MathInstruction<decimal>((a, b) => a / b));
И преобразование между типами:
var addIntAndDouble = new MathInstruction<int, double, double>((a, b) => a + b));
Это будет реализовано так:
class MathInstruction<TA, TB, TResult> : Instruction
{
private Func<TA, TB, TResult> callback;
public MathInstruction(Func<TA, TB, TResult> callback)
{
this.callback = callback;
}
public bool Exec(Context c)
{
var a = c.Pop<TA>();
var b = c.Pop<TB>();
var result = callback(a, b);
c.Push<TResult>(result);
return false;
}
}
// Convenience
class MathInstruction<T, TResult> : MathInstruction<T, T, TResult>
class MathInstruction<T> : MathInstruction<T, T, T>
Я представляю, что в вашем контексте просто есть Stack<object>
и PopINT
, PopBOOL
и т. Д., Просто добавьте аргумент и приведите. В этом случае вы, вероятно, можете просто использовать:
public T Pop<T>()
{
var o = stack.Pop();
return Convert.ChangeType(o, typeof(T));
}
public void Push<T>(T item)
{
stack.Push(item);
}
Обратите внимание, что это также может обрабатывать ваши логические операторы - например:
var logicalAnd = new MathInstruction<bool>((a, b) => a && b);
var logicalOr = new MathInstruction<bool>((a, b) => a || b);