2

我真的很讨厌使用IComparer——直到今天,在使用 .Net 多年之后,我仍然经常被那些 1 和 -1 弄糊涂。

我可以以某种方式用一些不言自明的名称替换比较结果值,而不必在每次比较调用后将输出整数转换为其他值吗?

我试图定义一个这样的枚举:

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

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

但这当然不会在没有演员表的情况下编译。

这当然也适用于IComparable.CompareTo

谢谢你的想法

4

4 回答 4

7

我更喜欢用这个来表达小于:

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

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


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

于 2012-01-17T19:40:29.207 回答
2

只创建常量怎么样?这样你就不必从枚举中投射。

public class CompareHelper
{
    public const int ALessThanB = -1;
    public const int Equal = 0;
    public const int AGreaterThanB = 1;
}
于 2012-01-17T19:37:31.780 回答
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;
    }
}
于 2012-01-17T19:46:38.967 回答
1

使用常量是危险的。IComparer.Compare的文档仅指定返回值应为“小于零” ifx < y或“大于零” if 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;
}
于 2012-01-17T19:52:34.687 回答