2009-09-03 8 views
6

任意の数値を受け入れることができるC#メソッドを記述したいと思います。次のようなものがあります:C#数値ベースクラス

public static T Sum(T a, T b) where T : number { // (not real code) 
    return a + b; 
} 

しかし、私が使ったほとんどの他の言語に存在するように、C#では "数字"の基本クラスはありません。数値の型はIComparable、IFormattable、IConvertible、IComparable、IEquatableですが、算術機能はないようです。それらはすべて、構造体であり、オブジェクトとは別の共通のスーパークラスはありません。 (私がC#の構造体に精通していないし、まるでそれらがクラスのようなものでもクラスとは違っていても、私がここで意味をねじれているなら、許してください)

私は何かがないか、 "a"と "b"が "+"のコンテキスト内にあることを正確に宣言することなく、 "a + b"を実行するメソッドをC#で記述する

+0

(コメントに返信しました**明らかにするために**キャスティングもオーバーロードもありません) –

+0

( 'IEnumerable.Sum'についてのあなたの他のコメントは、MiscUtilは' Sum'、 'Average'等 - using 'Operator'など) –

答えて

3

オーバーロードを使用する必要があります。 Mathクラスのように、すべての数値型をサポートするMath.Maxのような関数を使っています。

linkもCDで提案されています。

+0

Linq拡張メソッドのように、IEnumerable.Sumを使っていて、数値型の半分しか実装していません! – Ken

+0

必ずしもそうではありません。ジェネリックベースのソリューションがあります(詳細は私の答えを見てください)。 –

2

残念ながら、このようなクラス/インターフェイスは存在しません。

0

あなたができることは、ValueTypeを必要とするwhere T : structです。すべての数値はValueTypesです。

残念ながら、すべてのユーザー定義の構造体もそうですが、これは欠点です。すべての数値クラスを受け入れる特定のジェネリックはありません。

私もこれを示唆することを躊躇しています方法でTのタイプに対してランタイムチェックを考慮し、Tがint、長い、短い、float型、またはdoubleでない場合、スローされることがあります。残念なことに、これはコンパイル時にプログラマーを助けるものではありません。

2

int、その他の数値型はValueTypesです。すでに述べたように、あなたができることは、where T: structです。さて、型引数が追加を実装するかどうかを確認するためにリフレクションを使うことができます。しかし、それが良い考えであるかどうかは分かりません。

3

this SO questionを参照してください。

あなたはあなたのためにそれを使用したいネットコア数の種類ごとに別々の種類を作成するために喜んでいる場合にも、あなたは(いくつかの退屈な努力で)これを行うことができます...

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

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

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

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

0

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

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

私はすべてのオーバーロードとキャストを行うためのライブラリがありますが、「Operator.Add(a、b)」は「a +」という問題の解決策ではないと考えています。 b "は一般的ではない。冗長コードをたくさん書いてジェネリックにしたいのであれば、私はサードパーティのライブラリを必要としません。 :-) – Ken

+0

*過負荷やキャスティングはありません。これは本物のジェネリックベースのコードで、算術演算を行うことができるデリゲート(型ごと)をあらかじめコンパイルするためにExpressionを巧みに使用しています。 –

+0

'Add 'が実際にはジェネリックメソッド(' Add ')であることを明確にすると役に立ちます。この例では、 ''を自分で追加しなくて済むようにジェネリック型の推論を使用しています。しかしそれはまだそこにある。 –

関連する問題