12

私は単純なクランプを作成しようとしています(比較可能なものの値をバインドできるように...主にint、doubleなどの数値型の場合)

問題は、次のようにするとエラーが発生することですが、MSDN によると、 IComparable の CompareTo は null 値を処理できるはずです。
引用: 「定義上、すべてのオブジェクトは null より大きいと比較され、2 つの null 参照は互いに等しいと比較されます。」

public static T Clamp<T>(this T value, T min, T max)
    where T : IComparable<T>
{
    if (value.CompareTo(max) > 0)
        return max;

    if (value.CompareTo(min) < 0)
        return min;

    return value;
}



private Int32? _zip;
public Int32? Zip
{
    get
    {
        return _zip;
    }
    set
    {
        _zip = value.Clamp<Int32?>(0, 99999);
    }
}
4

2 に答える 2

15

@LBushkin Nullable< T > または T が言ったように? IComparable インターフェイスを実装していません。指定された解決策は問題ありませんが、単一責任の原則に従って、その点で特殊なクラス内にnull許容比較ロジックを配置することを好みます。また、Null許容型の比較にも使用できます。

たとえば、次のような汎用 Nullable 型比較クラスを作成できます。

public class NullableComparer<T> : IComparer<Nullable<T>>
      where T : struct, IComparable<T>
{

     public int Compare(Nullable<T> x, Nullable<T> y)
     {
        //Compare nulls acording MSDN specification

        //Two nulls are equal
        if (!x.HasValue && !y.HasValue)
            return 0;

        //Any object is greater than null
        if (x.HasValue && !y.HasValue) 
            return 1;

        if (y.HasValue && !x.HasValue)
            return -1;

        //Otherwise compare the two values
        return x.Value.CompareTo(y.Value);
     }

}

この場合、このクラスを次のように使用します。

public static T? Clamp<T>(this T? value, T? min, T? max)
    where T : struct
{
    var comparer = new NullableComparer<T>();

    if (comparer.Compare(value, max) > 0)
        return max;

    if (comparer.Compare(value, min) < 0)
        return min;

    return value;
}

ヘルパー ライブラリに保存するのに便利です。

それが役に立てば幸い!

于 2010-07-20T22:09:24.800 に答える
7

Int32?は の省略形であることを忘れないでくださいNullable<Int32>Nullable<T>は を実装していないため、IComparable<T>構造化されたコードはコンパイルされません。

ただし、メソッドをオーバーロードできます。

public static T? Clamp<T>(this T? value, T? min, T? max) 
    where T : struct, IComparable<T> 
{ 
    // your logic...
} 

もちろん、null 許容型を使用することを計画している場合は、null値をクランプする方法を定義する必要があります...

実際に値をクランプする必要がない場合はnull、最初にプロパティ ゲッターで null をチェックする方が簡単な場合があります。

public Int32? Zip
{
   ...
   set
   {
       _zip = value == null ? value : value.Value.Clamp<Int32>(0,99999);
   }

または、さらに良いことに、追加のオーバーロードの実装の一部にしてくださいClamp...

于 2010-07-20T21:41:02.627 に答える