C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: C#のジェネリックの制約について


(過去ログ 35 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■17818 / inTopicNo.1)  C#のジェネリックの制約について
  
□投稿者/ studyC# (1回)-(2008/05/02(Fri) 09:10:59)

分類:[C#] 

こんにちわ。初めて投稿します。
現在、C#(3.0)を勉強中です。よろしくお願いいたします。

C#のジェネリックについて質問があります。

例えば、次のような足し算や引き算を含むコードがあります。

class MyMath
{
    public MyMath()
    {

    }

    public int add(int x, int y)
    {
        return x + y;
    }

    public int minus(int x, int y)
    {
        return x - y;
    }
}

このコードだと、doubleの足し算や引き算をしたい場合には、add()やminus()をオーバーロードしなくてはいけなくなり面倒です。

そこで、ジェネリックを使い、

class MyMath<T>
{
    public MyMath()
    {

    }

    public T add(T x, T y)
    {
        return x + y;
    }

    public T minus(T x, T y)
    {
        return x - y;
    }
}

とすれば、うまくいくかと思いきや、T型は+や-ができるかわからないとコンパイラにはじかれました。
当然のことなのですが。。。

そこでwhereでTに対して+や-の演算ができるように制約をつけようと思っているのですが、制約に何を指定すればいいか探してみたのですがわかりませんでした。
そもそも、こういうことはできないのでしょうか><

わかる方がいらっしゃいましたら、ご助言いただけるとありがたいです。
すみませんが、よろしくお願いいたします。

引用返信 編集キー/
■17820 / inTopicNo.2)  Re[1]: C#のジェネリックの制約について
□投稿者/ Jitta (470回)-(2008/05/02(Fri) 09:23:47)
Jitta さんの Web サイト
2008/05/02(Fri) 09:24:51 編集(投稿者)

No17818 (studyC# さん) に返信
operator +
とかじゃないかな?

ちげ。。。質問の意味間違えた。無視してください。
引用返信 編集キー/
■17822 / inTopicNo.3)  Re[1]: C#のジェネリックの制約について
□投稿者/ 魔界の仮面弁士 (709回)-(2008/05/02(Fri) 09:28:54)
No17818 (studyC# さん) に返信
> 例えば、次のような足し算や引き算を含むコードがあります。
static で良いのでは無いか、という突っ込みはさておき。

> そこでwhereでTに対して+や-の演算ができるように制約をつけようと思っているのですが、
> 制約に何を指定すればいいか探してみたのですがわかりませんでした。
3.0 でどうなっているかは把握していませんが、2.0 においては
制約等では対処できなかったように思います。

> そもそも、こういうことはできないのでしょうか><
2.0 の時は、こんな方法で逃げていました。

static class MyMath<T>
{
    public static T Add(T x, T y)
    {
        return (T)Microsoft.VisualBasic.CompilerServices.Operators.AddObject(x, y);
    }

    public static T minus(T x, T y)
    {
        return (T)Microsoft.VisualBasic.CompilerServices.Operators.SubtractObject(x, y);
    }
}

引用返信 編集キー/
■17865 / inTopicNo.4)  Re[2]: C#のジェネリックの制約について
□投稿者/ studyC# (2回)-(2008/05/02(Fri) 16:47:44)
No17822 (魔界の仮面弁士 さん) に返信

回答ありがとうございます。

> static で良いのでは無いか、という突っ込みはさておき。

そうですね。このケースだとstaticですね^^
突っ込みありがとうございます。

> 2.0 の時は、こんな方法で逃げていました。

制約では対処できないのですねぇ。
なんかやり方がある筈と思ってましたが・・・orz

Microsoft.VisualBasic.CompilerServices.Operators.AddObjectなんてものがあるのですね。
勉強になりました。
親切な回答ありがとうございましたm(_ _)m

> ■No17818 (studyC# さん) に返信
>>例えば、次のような足し算や引き算を含むコードがあります。
> static で良いのでは無いか、という突っ込みはさておき。
>
>>そこでwhereでTに対して+や-の演算ができるように制約をつけようと思っているのですが、
>>制約に何を指定すればいいか探してみたのですがわかりませんでした。
> 3.0 でどうなっているかは把握していませんが、2.0 においては
> 制約等では対処できなかったように思います。
>
>>そもそも、こういうことはできないのでしょうか><
> 2.0 の時は、こんな方法で逃げていました。
>
> static class MyMath<T>
> {
> public static T Add(T x, T y)
> {
> return (T)Microsoft.VisualBasic.CompilerServices.Operators.AddObject(x, y);
> }
>
> public static T minus(T x, T y)
> {
> return (T)Microsoft.VisualBasic.CompilerServices.Operators.SubtractObject(x, y);
> }
> }
解決済み
引用返信 編集キー/
■17870 / inTopicNo.5)  Re[3]: C#のジェネリックの制約について
□投稿者/ 魔界の仮面弁士 (712回)-(2008/05/02(Fri) 18:04:52)
2008/05/02(Fri) 22:13:02 編集(投稿者)
# 解決チェックを外してしまっていたので、つけなおし。

■No17865 (studyC# さん) に返信
VB だったら、Option Strict Off にしておいて、
 Return CObj(a) + CObj(b)
とする手もあるのですけれどね。


> そうですね。このケースだとstaticですね^^
と思いましたが、型パラメータの指定を考えると、インスタンスメソッドの方が楽かも…。

同じ演算子を繰り返し使う場合、型引数を毎回指定して
 a = MyMath<System.Int32>.Minus(30, 12);
 b = MyMath<System.Int32>.Minus(30, 10);
と書かせるよりも、
 a = foo.Minus(30, 12);
 b = foo.Minus(30, 10);
のように書けた方が楽ですし。


もし、static にするのであれば、
  static class MyMath<T>
  {
    public static T Minus(T x, T y) { … }
  }
ではなく、
  static class MyMath
  {
    public static T Minus<T>(T x, T y) { … }
  }
とするのも手かも知れません。これなら利用時は、
 int c = MyMath.Minus(30, 8);
のように、型推論が使えますので。


>>2.0 の時は、こんな方法で逃げていました。
> 制約では対処できないのですねぇ。
> なんかやり方がある筈と思ってましたが・・・orz
C# は専門外なので、単に私が知らないだけかも知れませんけれどね。


> Microsoft.VisualBasic.CompilerServices.Operators.AddObjectなんてものがあるのですね。
他に使えそうなのは、Microsoft.JScript.Plus.DoOp とか、IL の動的生成とか。


演算効率を落としても良ければ、こんな手も。

public class MyMath<T>
{
    DataRow row;
    public MyMath()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("x", typeof(T));
        dt.Columns.Add("y", typeof(T));
        dt.Columns.Add("Plus", typeof(T)).Expression = "x+y";
        dt.Columns.Add("Minus", typeof(T)).Expression = "x-y";
        row = dt.Rows.Add();
    }

    private T DoOp(T x, T y, string method)
    {
        row["x"] = x;
        row["y"] = y;
        return (T)row[method];
    }

    public T Plus(T x, T y) { return DoOp(x, y, "Plus"); }
    public T Minus(T x, T y) { return DoOp(x, y, "Minus"); }
}

解決済み
引用返信 編集キー/
■17911 / inTopicNo.6)  Re[4]: C#のジェネリックの制約について
□投稿者/ studyC# (3回)-(2008/05/03(Sat) 15:07:37)
No17870 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士さん、またまた回答ありがとうございますm(_ _)m

>  a = MyMath<System.Int32>.Minus(30, 12);
>  b = MyMath<System.Int32>.Minus(30, 10);
> と書かせるよりも、
>  a = foo.Minus(30, 12);
>  b = foo.Minus(30, 10);
> のように書けた方が楽ですし。

なるほど。
確かにそうですね。

> static class MyMath
> {
> public static T Minus<T>(T x, T y) { … }
> }
> とするのも手かも知れません。これなら利用時は、
>  int c = MyMath.Minus(30, 8);
> のように、型推論が使えますので。

おぉぉ、型推論ですか!
確かに、これだと引数からTが推測できるので<>の指定がいらなくなるわけですね@@
勉強になります。ありがとうございます。

> C# は専門外なので、単に私が知らないだけかも知れませんけれどね。

えぇ><
これで専門外なのですが。。。
私ももっと精進しないと!!

ありがとうございました。

> 2008/05/02(Fri) 22:13:02 編集(投稿者)
>
> # 解決チェックを外してしまっていたので、つけなおし。
>
> ■No17865 (studyC# さん) に返信
> VB だったら、Option Strict Off にしておいて、
>  Return CObj(a) + CObj(b)
> とする手もあるのですけれどね。
>
>
>>そうですね。このケースだとstaticですね^^
> と思いましたが、型パラメータの指定を考えると、インスタンスメソッドの方が楽かも…。
>
> 同じ演算子を繰り返し使う場合、型引数を毎回指定して
>  a = MyMath<System.Int32>.Minus(30, 12);
>  b = MyMath<System.Int32>.Minus(30, 10);
> と書かせるよりも、
>  a = foo.Minus(30, 12);
>  b = foo.Minus(30, 10);
> のように書けた方が楽ですし。
>
>
> もし、static にするのであれば、
> static class MyMath<T>
> {
> public static T Minus(T x, T y) { … }
> }
> ではなく、
> static class MyMath
> {
> public static T Minus<T>(T x, T y) { … }
> }
> とするのも手かも知れません。これなら利用時は、
>  int c = MyMath.Minus(30, 8);
> のように、型推論が使えますので。
>
>
> >>2.0 の時は、こんな方法で逃げていました。
>>制約では対処できないのですねぇ。
>>なんかやり方がある筈と思ってましたが・・・orz
> C# は専門外なので、単に私が知らないだけかも知れませんけれどね。
>
>
>>Microsoft.VisualBasic.CompilerServices.Operators.AddObjectなんてものがあるのですね。
> 他に使えそうなのは、Microsoft.JScript.Plus.DoOp とか、IL の動的生成とか。
>
>
> 演算効率を落としても良ければ、こんな手も。
>
> public class MyMath<T>
> {
> DataRow row;
> public MyMath()
> {
> DataTable dt = new DataTable();
> dt.Columns.Add("x", typeof(T));
> dt.Columns.Add("y", typeof(T));
> dt.Columns.Add("Plus", typeof(T)).Expression = "x+y";
> dt.Columns.Add("Minus", typeof(T)).Expression = "x-y";
> row = dt.Rows.Add();
> }
>
> private T DoOp(T x, T y, string method)
> {
> row["x"] = x;
> row["y"] = y;
> return (T)row[method];
> }
>
> public T Plus(T x, T y) { return DoOp(x, y, "Plus"); }
> public T Minus(T x, T y) { return DoOp(x, y, "Minus"); }
> }
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -