Работа с IComparable.Сравните без магических чисел - PullRequest
2 голосов
/ 17 января 2012

Мне очень не нравится работать с IComparer - и по сей день, после многих лет работы с .Net, я все еще постоянно путаюсь с этими 1 и 1.

Могу ли я каким-либо образом заменить Сравнить значения результата с некоторыми самоочевидными именами без необходимости приведения выходных целых чисел к чему-либо еще после каждого Сравнить call?

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

public enum ComparerResult
{
    ALessThanB = -1,
    Equal = 0,
    AGreaterThanB = 1
}

if(comparer.Compare(a, b) == ComparerResult.ALessThanB)

Но это, конечно, не скомпилируется без приведения.

Это, конечно, также применимо IComparable.CompareTo .

Спасибо за ваши идеи

Ответы [ 4 ]

7 голосов
/ 17 января 2012

Я предпочитаю выражать меньше, чем:

if (comparer.Compare(a, b) < 0)

Это хорошая мнемоника, потому что вы используете тот же оператор для сравнения с нулем, как и для двух операндов.


Как Reddog напомнил мне в комментариях, спецификация для интерфейсов не требует -1 и 1 специально; это требует только отрицательных и положительных результатов. Таким образом, используемая в настоящее время логика не гарантирует работу во всех случаях.

2 голосов
/ 17 января 2012

Как насчет метода расширения на IComparable и IComparer?

public static class IComparableExtension
{
    public static ComparerResult NiceCompareTo(this IComparable a, IComparable b)
    {
        int result = a.CompareTo(b);
        if (result > 0) return ComparerResult.ALessThanB;
        if (result < 0) return ComparerResult.AGreaterThanB;
        return ComparerResult.Equal;
    }
}

public static class IComparerExtension
{
    public static ComparerResult NiceCompare(this IComparer c, IComparable a, IComparable b)
    {
        int result = c.Compare(a, b);
        if (result > 0) return ComparerResult.ALessThanB;
        if (result < 0) return ComparerResult.AGreaterThanB;
        return ComparerResult.Equal;
    }
}
2 голосов
/ 17 января 2012

Как насчет создания констант?Таким образом, вам не придется разыгрывать перечисления.

public class CompareHelper
{
    public const int ALessThanB = -1;
    public const int Equal = 0;
    public const int AGreaterThanB = 1;
}
1 голос
/ 17 января 2012

Использование констант опасно.Документация для IComparer.Compare только указывает, что возвращаемое значение должно быть «меньше нуля», если x < y, или «больше нуля», если x > y.Поэтому не следует полагать, что возвращаемое значение будет одним из [-1, 0, 1].

Вместо этого я бы предложил создать метод расширения на IComparer, который сделает всю работу за вас.

static MyCompare(this IComparable self, object x, object y)
{
    var result = self.Compare(x, y);
    if(result < 0) return ComparerResult.ALessthanB;
    if(result == 0) return ComparerResult.Equal;
    return ComparerResult.AGreaterThanB;
}
...