使用没有幻数的IComparable.Compare

时间:2012-01-17 19:34:54

标签: c# .net coding-style code-readability base-class-library

我真的很讨厌与IComparer合作 - 直到今天,经过多年与.Net的合作,我仍然经常被那些1和-1混淆。

我可以以某种自解释名称以某种方式替换Compare结果值,而不必在每次Compare调用后将输出整数转换为其他内容吗?

我尝试定义这样的枚举:

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

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

但是如果没有演员阵容,那当然不会编译。

这当然也适用于IComparable.CompareTo

感谢您的想法

4 个答案:

答案 0 :(得分:7)

我更喜欢这个表达少于:

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

这是一个很好的助记符,因为你使用相同的运算符与零进行比较,就像在两个操作数之间进行比较一样。


正如Reddog在评论中提醒我的那样,接口的规范并不特别要求-1和1;它只需要消极和积极的结果。因此,您目前使用的逻辑并不能保证在所有情况下都能正常工作。

答案 1 :(得分:2)

如何创建常量?这样你就不必从枚举中强制转换。

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

答案 2 :(得分: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;
    }
}

答案 3 :(得分: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;
}