使用IComparable.不使用幻数进行比较
本文关键字:比较 IComparable 使用 | 更新日期: 2023-09-27 18:20:48
我真的很讨厌与IComparer合作——在与.Net合作多年后,直到今天,我仍然经常被那些1和-1弄糊涂。
我是否可以用一些不言自明的名称替换Compare结果值,而不必在每次Compare调用后将输出整数强制转换为其他值?
我试图定义这样一个枚举:
public enum ComparerResult
{
ALessThanB = -1,
Equal = 0,
AGreaterThanB = 1
}
if(comparer.Compare(a, b) == ComparerResult.ALessThanB)
但是,如果没有强制转换,它当然不会编译。
这当然也适用于IComparableCompareTo.
感谢您的想法
我更喜欢用这个来表示小于:
if (comparer.Compare(a, b) < 0)
这是一个很好的助记符,因为在两个操作数之间使用相同的运算符与零进行比较。
正如Reddog在评论中提醒我的那样,接口规范并不特别要求-1和1;它只需要消极和积极的结果。因此,不能保证您当前使用的逻辑在所有情况下都能工作。
只创建常量怎么样?这样就不必从枚举中进行强制转换。
public class CompareHelper
{
public const int ALessThanB = -1;
public const int Equal = 0;
public const int AGreaterThanB = 1;
}
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;
}
}
使用常量是危险的。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;
}