2009-08-28 20 views
21

可能性の重複:
C# generic constraint for only integers「実数」型のC#総称制約はありますか?

挨拶!

私はデカルト座標系をC#で設定しようとしていますが、自分自身の座標値の数値型に制限したくありません。時には整数でもよいし、文脈によっては有理数でもよい。

これは私には「ジェネリッククラス」と叫びますが、タイプをインテグラルポイントと浮動小数点の両方に制限する方法がわかりません。私は自由のこのレベルをしたい場合、私はそれがに来るとき、私は「typeof演算(T)」悪夢のために選任しています、

public class Point<T> where T : [SomeClassThatIncludesBothIntsandFloats?] { 
    T myX, myY; 

    public Point(T x, T y) { 
     myX = x; 
     myY = y; 
    } 
} 

Point<int> pInt = new Point<int>(5, -10); 
Point<float> pFloat = new Point<float>(3.14159, -0.2357); 

...実数のいずれかの概念をカバーするクラスを見つけることができないよう私のクラス内の計算、bool、文字列、オブジェクトなどの除外?それとも、悪いことに、それぞれの内部の数式を使って、それぞれのタイプの番号を扱うクラスを作ることにしましたか?

ご協力いただければ幸いです。ありがとう!

+10

これは非常に頻繁に要求される機能です。私たちはコンパイラ/ランタイムの将来のリリースの可能性を考慮していますが、優先順位リストではそれほど高くないので、これを何らかの約束として解釈しません。覚えておいて、私たちには可能な機能がたくさんあり、特定のリリースではほんの一握りのものしか入手できません。それは確かに我々のレーダーにあります。 –

+1

これは知っておいてよかった、エリック。私はC#の新機能ですが、Javaをベースにしていますので、次元をジャンプするのと同じですが、似ていますが、あなたが「ハァッ」になるのに十分な違いはありますか?かつてありませんでした。 ;) – Syndog

+3

他の人には、あなたのすべての応答に感謝します。皆さんはこれで終わりです!私はいつも私はGoogleのC#の質問stackoverflow.comは、結果に目立ってランクされるのも不思議ではありません。 – Syndog

答えて

16

このような制約は定義できませんが、実行時に型をチェックできます。それは計算をするためにあなたを助けません。

あなたが計算を行いたい場合は、このようなものはオプションで次のようになります。同様に

class Calculations<T, S> where S: Calculator<T>, new() 
{ 
    Calculator<T> _calculator = new S(); 

    public T Square(T a) 
    { 
     return _calculator.Multiply(a, a); 
    } 

} 

abstract class Calculator<T> 
{ 
    public abstract T Multiply(T a, T b); 
} 

class IntCalculator : Calculator<int> 
{ 
    public override int Multiply(int a, int b) 
    { 
     return a * b; 
    } 
} 

、あなたが必要FloatCalculatorし、任意の操作を定義します。特に高速ですが、C#4.0 dynamic構造よりも高速です。

var calc = new Calculations<int, IntCalculator>(); 
var result = calc.Square(10); 

副作用は、あなたがそれに渡すタイプが一致Calculator<T>実装を持っている場合にのみCalculatorをインスタンス化することができるということですので、あなたは、実行時の型チェックを行う必要はありません。

これは基本的に、Hejlsbergがthis interviewで言及していた問題です。個人的に私はまだ何らかの基底型を見たいと思っています:)

+1

そうですね。基本的に私の "プリミティブ"型を共通のインタフェースを実装しているクラスにラップし、それに基づいて制約します。ありがとう、トール! – Syndog

+0

.NET 3.5には、ジェネリックスでできることがまだあります。詳細は私の答えを見てください。 –

5

これは既知の問題です。算術クラスが同じクラスから到着しないためです。だからあなたはそれを制限することはできません。あなたができる

唯一のものは

where T : struct 

ですが、あなたが望む正確ではないthatsの。

ここに特定の問題へのリンクがあります。

Arithmetic types like int,double,decimal should implement IArithmetic<T>

+0

ちょっとスタン、ただあなたにそれがかなり助けていることを知らせたいと思っていました。 1回のストロークで、Tを構造体から継承させると、すべての値型の実行時チェックが不要になります。ありがとう、芽! – Syndog

+2

リンクが「ページが見つかりません」と表示されます。 – weberc2

0

Thi sが役に立つかもしれません。あなたは、あなたが望むものを達成するためにジェネリッククラスを使用しなければなりません。

0

C#では現在、値型に型制約がありません。あまりにもずっと前に私は関連する質問をしました。

Enum type constraints in C#

0

このIPointを実装する別々のクラスを持つことには向いていますか?

ような何か:

public interface IPoint<T> 
{ 
    T X { get; set; } 
    T Y { get; set; } 
} 

public class IntegerPoint : IPoint<int> 
{ 

    public int X { get; set; } 
    public int Y { get; set; } 
} 

を計算が右とにかく、それぞれの実装で異なることがありますと?

ダン#

+2

さて、計算は、整数値または浮動小数点値を使用して実装されているかどうかにかかわらず、実際には同じです。それ以外の場合は、ジェネリックや継承なしでそれぞれの型を実装する2つの別々のクラスを作成します。しかし、式は同じなので、クラス間でコードを重複させたくありません。お返事をありがとうございます! – Syndog

3

ソリューションを設定するために、そしてそれが行われた理由を認識していない開発者に混乱を招く可能性が面倒ですが、あなたが実際に、これを行うことができます。 ...

CTS Int32のファサードとして機能するsay、MyInt、およびMyDecimalの2つの構造体を作成します(これらには内部フィールドが含まれています)各入力パラメータとしてコアCTS型のインスタンスを取るctorのを持っていなければならない)。そのそれぞれのタイプの...

が作る、それぞれが自分の一般的な方法で、次にINumeric

と呼ばれる空のインターフェイスを実装してくださいこのインタフェースに基づく制約 欠点は、これらのメソッドを使用するすべての場所で、コアCTSタイプではなく適切なカスタムタイプのインスタンスを作成し、そのカスタムタイプをメソッドに渡す必要があることです。

注:コアCTSタイプのすべての動作を正しくエミュレートするためにカスタム構造体をコーディングするのは面倒な作業です...組み込みのCLRインターフェイス(IComparableなど)をいくつか実装し、ブール演算子...

12

これはよくある質問です。 .NET 3.5を使用している場合は、Operatorクラスを使用して、MiscUtilに多くのサポートがあります。これは、組み込み型および演算子( "持ち上げられた"演算子を含む)を持つ任意のカスタム型をサポートします。特に、これは、例えば、ジェネリックで使用可能:

public static T Sum<T>(this IEnumerable<T> source) { 
    T sum = Operator<T>.Zero; 
    foreach (T value in source) { 
     if (value != null) { 
      sum = Operator.Add(sum, value); 
     } 
    } 
    return sum; 
} 

または別例えば 。 Complex<T>

+0

興味深い。 LINQの式ツリー機能を使用しているようですが、すぐに各ビットを評価しますか? – Thorarin

+0

内部的には、式ツリーを使用して、算術演算を行うことができるデリゲートを事前コンパイル(型ごとに1回のみ)します。 –

1

あなたは署名があまりにもDateTimeに準拠

public class Point<T> where T : struct, IComparable, IFormattable, IConvertible, 
           IComparable<T>, IEquatable<T> { 
} 

さらにいくつかの実装に近づくことができます。フレームワークからより多くの型を指定できるかどうかはわかりません。とにかくこれは問題の一部を解決するだけです。基本的な数値演算を行うには、数値型をラップし、標準演算子の代わりに汎用メソッドを使用する必要があります。 See this SO questionいくつかのオプションがあります。

関連する問題