何も考えずに

とりあえず考えなしに、素直に制約インターフェスを書いてみる。

/// Four Rule Of Arithmetic -able
public interface IFROAble
{
  T Add(T left, T right);
  T Substract(T left, T right);
  T Multiply(T left, T right);
  T Divide(T left, T right);
  T Negate(T value);
}

使ってみる。

static T Sum(params T[] values) where T : IFROAble
{
  if (values == null) throw new ArgumentNullException("values");

  T sum = default(T);
  foreach (T value in values)
  {
    sum = sum.Add(sum, value);
  }

  return sum;
}

あれ、T を演算対象の型としてみると、この制約に出てくる T は実装を持った型じゃないといけないから T では耐えられない。
と、ここで数十秒考えたが、素直に

 static T Sum(params T[] values) where I : IFROAble
{
  if (values == null) throw new ArgumentNullException("values");

  I fra = default(I);
  T sum = default(T);
  foreach (T value in values)
  {
    sum = fra.Add(sum, value);
  }

  return sum;
}

と Type と Implementation を別個で受け取るように改めた。
あまり省略しまくった名称は好きじゃないのだが、頭文字をとって T, I とした。

そして使用する。

class Int32FROAImplements : IFROAble
{
  public int Add(int left, int right)
  {
    return left + right;
  }

  public int Substract(int left, int right)
  {
    return left - right;
  }
  // :
  // :たっぷり略
  // :
}

public static void Main()
{
  Console.WriteLine(Sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
  Console.WriteLine(
      Sum(0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1));
}

とりあえず問題なく動作するものができた。