提问者:小点点

如何比较泛型类型的值?


如何比较泛型类型的值?

我把它简化为一个最小的样本:

public class Foo<T> where T : IComparable
{
    private T _minimumValue = default(T);

    public bool IsInRange(T value) 
    {
        return (value >= _minimumValue); // <-- Error here
    }
}

错误是:

运算符“>=”不能应用于“t”和“t”类型的操作数。

究竟是什么!? T已经被约束为IComparable,即使将其约束为值类型(where t:struct),我们仍然不能应用任何运算符>>>!=。 (我知道对于==!=存在涉及equals()的变通方法,但它对关系运算符没有帮助)。

所以,有两个问题:

  1. 为什么我们会观察到这种怪异的行为? 是什么使我们无法比较已知为IComparable的泛型类型的值呢? 它不是在某种程度上破坏了泛型约束的全部目的吗?
  2. 如何解决此问题,或至少解决此问题?

(我意识到已经有一些问题与这个看似简单的问题相关--但没有一个线程给出详尽的或可行的答案,所以在这里。)


共3个答案

匿名用户

IComparable不会重载>=运算符。 您应该使用

value.CompareTo(_minimumValue) >= 0

匿名用户

运算符重载问题

不幸的是,接口不能包含重载运算符。 尝试在编译器中键入以下内容:

public interface IInequalityComaparable<T>
{
    bool operator >(T lhs, T rhs);
    bool operator >=(T lhs, T rhs);
    bool operator <(T lhs, T rhs);
    bool operator <=(T lhs, T rhs);
}

我不知道他们为什么不允许这样做,但我猜这会使语言定义复杂化,而且用户很难正确地实现。

要么是这样,要么是设计师不喜欢这种滥用的可能性。 例如,假设对类MagicMRMeow执行>=比较。 甚至在类矩阵上。 关于这两个值的结果意味着什么?; 尤其是在有歧义的时候?

官方的解决办法

由于上述接口不合法,我们有IComparable接口来解决这个问题。 它不实现运算符,只公开一个方法,int CompareTo(T other);

请参阅http://msdn.microsoft.com/en-us/library/4d7sx9hd.aspx

int结果实际上是三位或三进制(类似于boolean,但有三种状态)。 下表解释了结果的含义:

Value              Meaning

Less than zero     This object is less than
                   the object specified by the CompareTo method.

Zero               This object is equal to the method parameter.

Greater than zero  This object is greater than the method parameter.

使用变通办法

为了执行value>=_minimumvalue的等价物,您必须改为编写:

value.CompareTo(_minimumValue) >= 0

匿名用户

如果value可以为null,则当前答案可能失败。 请使用类似以下内容:

Comparer<T>.Default.Compare(value, _minimumValue) >= 0