Сравнение чисел Получить другой результат
Я уверен, что есть простое объяснение, но не могу выработать следующее:
const short amount = 30000;
bool isGreater =
ComparableExtensions.IsGreaterThan(amount, 29000); //returns true
bool isGreaterThan2 =
amount.IsGreaterThan<short>(29000);//returns false
public static class ComparableExtensions
{
public static bool IsGreaterThan<T>(this T leftValue, T rightValue)
where T : struct, IComparable<T>
{
var result = leftValue.CompareTo(rightValue) == 1;
return result;
}
}
Это из-за того, что я поставил "Структуру"?
какие-либо объяснения или предложения?
Спасибо
4 ответа
Нет, ваша ошибка при использовании leftValue.CompareTo(rightValue) == 1
,
Вместо этого, скажем leftValue.CompareTo(rightValue) > 0
,
Все, что вы знаете, это CompareTo
возвращается < 0
если leftValue
меньше чем rightValue
, 0
если leftValue
равняется rightValue
а также > 0
если leftValue
больше, чем rightValue
, Вы можете не только проверить на равенство с 1
,
Кроме того, причина того, что вы видите разное поведение между двумя вызовами, заключается в том, что в первом случае вы звоните IsGreaterThan<int>
потому что буквальная константа 29000
будет интерпретироваться как Int32
, но во втором случае вы явно говорите short
так что это будет интерпретироваться как Int16
,
Компилятор выводит универсальный тип при первом (статическом) вызове. Оно использует Int32
, Int32.CompareTo
метод возвращает 1 больше чем.
Во-вторых, ваш звонок от Int16
сил T
быть Int16
, Int16.CompareTo
возвращает фактическую разницу между двумя значениями *. Юридический под IComparable
(для которого требуется только значение> 0) - но достаточно разное для сбоя вашего вызова.
Явное приведение первого вызова к short
также приведет к сбою.
*
Нет, я понятия не имею, почему Int16 реализован таким образом. Кажется, "потому что это может быть"(Byte
ведет себя так же) - так как вы можете вычитать, не опасаясь переполнения (так как вы приводите более широкий тип для результата). Требуется больше работы, чтобы сделать что-то подобное для Int32
что, я полагаю, не стоило усилий.
Посмотрите документацию для IComparable
и возвращаемое значение CompareTo
метод. В нем говорится, что он вернет значение меньше нуля, если a < b
, точно ноль, если a == b
и значение больше нуля, если a > b
, Тем не менее, вы сравниваете возвращаемое значение с 1
, Нет никаких гарантий, что этот метод когда-либо вернется 1
, Вместо этого вы должны сделать:
var result = leftValue.CompareTo(rightValue) > 0;
Электрический ток short.CompareTo()
реализация примерно такая:
public int CompareTo(short value)
{
return (int)(this - value);
}
в то время как int.CompareTo()
реализация примерно такая:
public int CompareTo(int value)
{
if (this < value)
{
return -1;
}
if (this > value)
{
return 1;
}
return 0;
}
В первом случае общий T
тип выводится как Int32
так как 29000
является Int32
строковый литерал и поэтому int.CompareTo()
метод называется.
Во втором случае вы специально говорите, что T
является short
а затем short.CompareTo()
называется.
Как уже отмечалось в других ответах, IComparable<T>
спецификация не гарантирует возврат всегда:
0 : if the numbers are equal
-1 : if the number is lower than the other
1 : if the number is greater than the other
но просто говорит, что должно вернуться
0 : if the numbers are equal
a number < 0 : if the number is lower than the other
a number > 0 : if the number is greater than the other