假设我有一个实现IComparable的类型。
我原本以为期望运营商==
,!=
,>
,<
,>=
和<=
合理通过调用CompareTo自动“正常工作”,但如果我想使用它们,我必须全部覆盖它们。
从语言设计的角度来看,有这样一个很好的理由吗?是否有任何情况下,A>B
对Compare(A,B)>0
采取不同的行为真的很有用?
答案 0 :(得分:27)
整个局势令人烦恼。 C#有太多表达平等和不平等的方法:
它们都具有微妙的不同语义,除了静态Equals之外,没有一个自动使用另一个,并且没有一个实际上具有我想要的行为。根据两个操作数的编译时类型调度静态方法;根据操作数的 one 的运行时类型调度虚方法/接口方法,使操作不对称;一方的类型比另一方的类型更重要。
我无法想象有人认为我们所处的情况很好;没有任何约束,这不是将要发展的东西。但是托管语言设计者确实有约束:CLR不在接口契约或双虚拟调度中实现静态方法,或者在泛型类型参数上设置运算符约束的能力。因此,多种解决方案已经发展到解决平等/不平等问题。
我认为CLR和C#设计师要回过头来告诉他们过去自己CLR的v1中应该有哪些功能,接口中的某种形式的静态方法会在列表中占据很高的位置。如果接口中有静态方法,那么我们可以定义:
interface IComparable<in T, in U>
{
static bool operator <(T t, U u);
static bool operator >(T t, U u);
... etc
然后如果你有:
static void Sort<T>(T[] array) where T : IComparable<T, T>
然后,您可以使用<
和==
等运算符来比较元素。
答案 1 :(得分:11)
两个主要原因:
更新根据Eric Lippert等,以下是针对UDT类型的C#中比较运算符的相应标准实现:
public int CompareTo(UDT x) { return CompareTo(this, x); }
public bool Equals(UDT x) { return CompareTo(this, x) == 0; }
public static bool operator < (UDT x, UDT y) { return CompareTo(x, y) < 0; }
public static bool operator > (UDT x, UDT y) { return CompareTo(x, y) > 0; }
public static bool operator <= (UDT x, UDT y) { return CompareTo(x, y) <= 0; }
public static bool operator >= (UDT x, UDT y) { return CompareTo(x, y) >= 0; }
public static bool operator == (UDT x, UDT y) { return CompareTo(x, y) == 0; }
public static bool operator != (UDT x, UDT y) { return CompareTo(x, y) != 0; }
public override bool Equals(object obj)
{
return (obj is UDT) && (CompareTo(this, (UDT)obj) == 0);
}
只需添加private static int CompareTo(UDT x, UDT y)
的自定义定义并搅拌。