2012-01-17 2 views
2

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

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

Я попытался определить перечисление как это:

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

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

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

Это, конечно же, относится к IComparable.CompareTo.

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

ответ

7

Я предпочитаю, чтобы это выразить менее чем:

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

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


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

+2

Это также хорошо, потому что возвращаемое значение необязательно должно быть равным -1, 0 или 1. Оно должно быть меньше нуля, нуля или больше нуля. – Reddog

+1

@ Реддог, на самом деле, да, я просто проверил спецификацию для метода, и он не гарантирует, что он вернет -1 или 1 конкретно. –

2

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

public class CompareHelper 
{ 
    public const int ALessThanB = -1; 
    public const int Equal = 0; 
    public const int AGreaterThanB = 1; 
} 
2

Как насчет метода расширения на 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; 
    } 
} 
1

Использование констант опасно. documentation для 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; 
} 
Смежные вопросы