using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace GenericMath { //(c) Roger Alsing , www.rogeralsing.com 2008 //Demo code only, lacking exception handling and a few operators public class Number { private T value; private static readonly Func Add = CompileDelegate(Expression.Add); private static readonly Func Sub = CompileDelegate(Expression.Subtract); private static readonly Func Mul = CompileDelegate(Expression.Multiply); private static readonly Func Div = CompileDelegate(Expression.Divide); private static readonly Func Mod = CompileDelegate(Expression.Modulo); private static Func CompileDelegate(Func operation) { try { //create two inprameters ParameterExpression leftExp = Expression.Parameter(typeof(T), "left"); ParameterExpression rightExp = Expression.Parameter(typeof(T), "right"); //create the body from the delegate that we passed in Expression body = operation(leftExp, rightExp); //create a lambda that takes two args of T and returns T LambdaExpression lambda = Expression.Lambda(typeof(Func), body, leftExp, rightExp); //compile the lambda to a delegate that takes two args of T and returns T Func compiled = (Func)lambda.Compile(); return compiled; } catch { //type T does not support math operations return null; } } private Number(T value) { this.value = value; } public static implicit operator Number(T a) { return new Number(a); } public static implicit operator T(Number number) { return number.value; } public static Number operator +(Number a, Number b) { return new Number(Add(a.value, b.value)); } public static Number operator -(Number a, Number b) { return new Number(Sub(a.value, b.value)); } public static Number operator /(Number a, Number b) { return new Number(Div(a.value, b.value)); } public static Number operator *(Number a, Number b) { return new Number(Mul(a.value, b.value)); } public static Number operator %(Number a, Number b) { return new Number(Mod(a.value, b.value)); } public static bool IsNumeric { get { //ugly hack.. //requires an exception in the delegate generator //in order to determine if the type supports math operations if (Add == null) return false; else return true; } } } }