web-dev-qa-db-ja.com

数値型に一致する汎用制約

私が構築している流testingなテストフレームワークで使用される数値型の拡張メソッドを作成しようとしています。基本的に、私はこれをやりたい:

public static ShouldBeGreaterThan<T>(this T actual, T expected, string message)
    where T : int || T: double || etc...

where T : structは、stringおよびboolにも一致するため、そうではありません。数値型のみを一致させるためにできることはありますか? (具体的には>および<演算子を実装する型なので、それらを比較できます...これが日付を一致させることを意味する場合、それは本当に重要ではありません-拡張機能はまだ実行します私が期待するもの。)

77
Tomas Aschan

この場合、ジェネリックをIComparableインターフェイスに制限します。これにより、CompareToメソッドにアクセスできます。これは、このインターフェイスでShouldBeGreaterThanの質問に答えることができるためです。

数値型はそのインターフェイスを実装しますが、文字列でも機能するという事実はそれほど気にするべきではありません。

53
flq
where T : struct, 
          IComparable, 
          IComparable<T>, 
          IConvertible, 
          IEquatable<T>, 
          IFormattable

これは数値制約に最も近いものです。すべての数値型はこれら5つのインターフェイスを実装しますが、IFormattableはboolによって実装されておらず、文字列は参照型であるため、適用できません。

これらを実装するものが他にもいくつかあります。たとえば、DateTimeです。したがって、実際には必要ではありませんが、必要のない多くのインスタンス化を防ぎます。

40
Mark H
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T>
{
    return actual.CompareTo(comp) > 0;
}

必要に応じて、構造体制約を追加することもできます。

16
Lee

フィルタとして使用するINumericのような一般的なものはないため、数値だけに制限するのは困難です。実際、ここで最も簡単なアプローチは、not制約を主張し、メソッド内でComparer<T>.Default.Compareを使用することだと思います。

この組み込み型は、ジェネリックIComparable<T>と非ジェネリックIComparableの両方をサポートし、Nullable<T>を介してref-types、value-types、lifted usageをサポートします。

完全なoperatorの使用法については、 MiscUtilのOperator class およびGreaterThanなどをご覧ください。 really(インターフェースではなく)演算子を使用する場合に便利です。また、Addなどの他の演算子へのアクセスも提供します。

6
Marc Gravell

Stackoverflowには、この種の質問が散らばっています。 この検索を見てください 。 C#は、数値で制約されたジェネリック型を定義する方法をサポートしていません。残念ながら、最善の方法は、すべてのオブジェクトに拡張メソッドを実装し、タイプに基づいて切り替えを行うか、int、double、floatなどのメソッドのセットを作成することです。

4
Jake Pearson

この回避策が役立つ場合があります: ポリシーを使用した回避策 。コンパイル時の安全性を提供します。

0
Sergey Shandar