Я пытаюсь создать простой Зажим (так, чтобы я мог, связал значения чего-либо сопоставимого... главным образом для типов числа, таких как интервал, дважды, и т.д.),
Проблема состоит в том, если я делаю следующий, я получаю ошибку, но согласно 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);
}
}
Помните, 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
...
Как сказал @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;
}
Удобно для сохранения в вашей библиотеке помощников.
Надеюсь, это поможет!