C# generics aren't bad, they just aren't always what you need completely. I would love to have both C# generics and C++ templates for places (like this) where generics just doesn't cut it.
Anywho, the problem of "take an arbitrary type and perform these operations on it" is still possible, just not with generics alone. Enter the world of Dynamic Methods:
using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Linq.Expressions;using System.Text;using NUnit.Framework;namespace ConsoleApplication1{ [TestFixture] public class Program { static void Main(string[] args) { const int it = 100000000; int n, d; Benchmark(it, out n, out d); Console.WriteLine("Iterations: {0}", 1000000); Console.WriteLine("Static: {0}", n); Console.WriteLine("Dynamic: {0}", d); Console.Read(); } static void Benchmark(int iterations, out int nondynamic, out int dynamic) { var dwrap = CreateWrap<int>(); Stopwatch w = new Stopwatch(); w.Start(); for (int i = 0; i < iterations; i++) Wrap(5, 0, 10); w.Stop(); nondynamic = (int)w.ElapsedMilliseconds; w.Reset(); w.Start(); for (int i = 0; i < iterations; i++) dwrap(5, 0, 10); w.Stop(); dynamic = (int)w.ElapsedMilliseconds; } [Test] public void WrapIntTest() { var dynamicWrap = CreateWrap<int>(); Assert.AreEqual(Wrap(5, 1, 100), dynamicWrap(5, 1, 100)); } [Test] public void WrapFloatTest() { var dynamicWrap = CreateWrap<float>(); Assert.AreEqual(Wrap(5f, 1f, 100f), dynamicWrap(5, 1, 100)); } static int Wrap(int value, int min, int max) { return ((value - min) % (max - min + 1)) + min; } static float Wrap(float value, float min, float max) { return ((value - min) % (max - min + 1)) + min; } static Func<T, T, T, T> CreateWrap<T>() { var pValue = Expression.Parameter(typeof(T), "value"); var pMin = Expression.Parameter(typeof(T), "min"); var pMax = Expression.Parameter(typeof(T), "max"); var valueMinusMin = Expression.Subtract(pValue, pMin); var maxMinusMin = Expression.Subtract(pMax, pMin); var maxMinusMinPlus = Expression.UnaryPlus(maxMinusMin); var mod = Expression.Modulo(valueMinusMin, maxMinusMinPlus); var finalAdd = Expression.Add(mod, pMin); return Expression.Lambda<Func<T, T, T, T>>(finalAdd, new[] { pValue, pMin, pMax }).Compile(); } }}
(Updated with benchmarks, since I figured the next thing to come out of someone's mouth will involve performance)
If you define something that is not supported (does not implement +, -, %, and ++) then you will get an InvalidOperationException when calling CreateWrap<>(). Otherwise, it'll produce pretty much the same code as:
static T X(T value, T min, T max) { var a = value - min; var b = max - min; b++; var c = a % b; return c + min; }
Performance-wise, its nearly the same. Dynamic methods are slightly slower than actual code, but its still pretty damn impressive that it is so close.