2012-01-17 53 views
2

我真的很討厭使用IComparer - 直到今天,經過多年的.NET工作,我仍然經常被那些1s和-1s弄糊塗了。使用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 2012-01-17 19:44:51

+1

@Reddog,實際上,是的,我只是檢查了該方法的規範,並不能保證它會返回-1或1。 – 2012-01-17 19:47:06

2

如何創建常量?這樣你就不必從枚舉中拋出。

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

如何在IComparableIComparer上使用擴展方法?

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

使用常量是危險的。 IComparer.Compare的documentation僅指定返回值應該爲「小於零」(如果是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; 
}