The road to C# master trapemiya

C#を中心に、.NETの話題を取り上げます。

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  255  : 記事  1  : コメント  771  : トラックバック  30

ニュース

Since 2005年10月26日

わんくま同盟

わんくま同盟

Microsoft MVP


Visual Developer - Visual C#

記事カテゴリ

書庫

日記カテゴリ

演算にジェネリックが含まれる場合の対処方法 MSDNフォーラムの以下の質問について考えてみた。

Generics で四則演算がしたい。
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=522960&SiteID=7

さて、ここからが考察です。まず、下記のコードを実行すると、次のようなエラーが出る。
class testOperator<T>
{
  public static T Add(T a, T b)
  {
    return a + b;
  }
}

エラー 1 演算子 '+' を 'T' と 'T' 型のオペランドに適用することはできません。
Tはoperator +を実装しているとは限らないので、言われてみれば当たり前のことである。しかし、プログラマがintやdoubleなどを想定していた場合、あまりに無情である。なんで~!どうしてできないの~!っていうことになる。そこで、Tにはoperator +を実装されたものしか使いませんよという制約を付けることによって許してもらえないだろうか?例えば、
class testOperator<T> where T:IOperator
のようにである。IOperatorはここで勝手に付けた名前であり、一連のOperator演算子を実装しているものとします。
というわけでC# 3.0辺りでなんとかなりませんか?

ちなみに上の代替コードの例は以下のようになります。

interface ICalculator<T>
{
  T Add(T a, T b);
}

struct IntCalculator : ICalculator<int> { public int Add(int a, int b) { return a + b; }
}
class testOperator<T, C> where C : ICalculator<T>, new() { public static T Add(T a, T b) { C calculator = new C();
return calculator.Add(a, b); } }

なお、calculator.Add(a, b)ではなく、本当にa + bを返したい場合は、以下のように少し複雑になる。ポイントとしては、Tにoperator +が実装されていることをコンパイラにわからせるしかない。したがって、Tをstructでラップし、そのstructでoperator +を定義することになる。

interface ICalculator<T>
{
  T Add(T a, T b);
}

struct IntCalculator : ICalculator<int> { public int Add(int a, int b) { return a + b; }
}
struct Number<T, C> where C : ICalculator<T>, new() { private T _Value; private static C calculator = new C();
private Number(T Value) { this._Value = Value; }
public T Value { get { return _Value; } }
public static implicit operator Number<T, C>(T a) { return new Number<T, C>(a); }
public static implicit operator T(Number<T, C> a) { return a._Value; }
public static Number<T, C> operator +(Number<T, C> a, Number<T, C> b) { return calculator.Add(a.Value, b.Value); } }
class testOperator<T, C> where C : ICalculator<T>, new() { public static T Add(T a, T b) { C calculator = new C();
return (Number<T, C>)a + (Number<T, C>)b; } }

(参考) Using generics for calculations http://www.codeproject.com/csharp/genericnumerics.asp
投稿日時 : 2006年7月6日 11:53

コメント

# re: 演算にジェネリックが含まれる場合の対処方法 2006/07/06 16:16 渋木宏明(ひどり)
そっかー、Complex<T> を書くのもちょっと辛いですね。


# [.NET]演算子に関するセマンティクスが保存される Generic 型生成 ― Expression Tree による実行時コード生成 ― 2006/08/01 15:08 NyaRuRuの日記
「菊池 Blog」より. たとえば、 class X&#60;T&#62; { bool IsEquals( T x,T y ) { return x==y; } } ==はobjectにも定義されているわけで、どのようなTに対しても本来は使用できます。 しかし上記のコードはコンパイルエラーになります。 op_Equalsがあるか無いかによって

# re: 演算にジェネリックが含まれる場合の対処方法 2008/06/12 11:40 trapemiya
お勧め関連記事発見!

ジェネリックで加算は無理?
http://blog.livedoor.jp/gushwell/archives/51533037.html

Post Feedback

タイトル
名前
Url:
コメント