Nullable универсальный тип используется с IComparable. Действительно ли это возможно?

Я пытаюсь создать простой Зажим (так, чтобы я мог, связал значения чего-либо сопоставимого... главным образом для типов числа, таких как интервал, дважды, и т.д.),

Проблема состоит в том, если я делаю следующий, я получаю ошибку, но согласно IComparable's MSDN CompareTo, как предполагается, может обработать нулевые значения.
Кавычка: "По определению любой объект выдерживает сравнение больше, чем пустой указатель, и две нулевых ссылки выдерживают сравнение равный друг другу".

public static T Clamp(this T value, T min, T max)
    where T : IComparable
{
    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(0, 99999);
    }
}

10
задан m-y 20 July 2010 в 21:37
поделиться

2 ответа

Помните, Int32? - это сокращение для Nullable. Поскольку Nullable не реализует IComparable, ваш код в таком виде не будет компилироваться.

Однако, вы можете перегрузить метод:

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

Конечно, если вы планируете работать с nullable типами, вы должны определить, как вы будете зажимать null значения...

Если вам не нужно зажимать null значения, может быть проще сначала проверить наличие null в геттере свойства:

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

Или, что еще лучше, сделать это частью реализации дополнительной перегрузки к Clamp...

7
ответ дан 3 December 2019 в 18:30
поделиться

Как сказал @LBushkin Nullable< T > или T? не реализует интерфейс IComparable. Данное решение нормально, однако я предпочитаю иметь логику сравнения nullable в специализированном классе, следуя Принципу единой ответственности, а также, что может быть использовано для сравнения любых Nullable типов.

Например, вы можете создать общий класс Nullable type comparer вот так:

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;
}

Удобно для сохранения в вашей библиотеке помощников.

Надеюсь, это поможет!

14
ответ дан 3 December 2019 в 18:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: