Сравнение чисел Получить другой результат

Я уверен, что есть простое объяснение, но не могу выработать следующее:

     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
Другие вопросы по тегам