如何比较genericstypes的值?

如何比较genericstypes的值?

我已经减less到最小的样本:

public class Foo<T> where T : IComparable { private T _minimumValue = default(T); public bool IsInRange(T value) { return (value >= _minimumValue); // <-- Error here } } 

错误是:

运算符'> ='不能应用于'T'和'T'types的操作数。

到底怎么回事!? T已经被限制为IComparable ,甚至当它限制为值types( where T: struct )时,我们仍然不能应用任何运算符<><=>===!= 。 (我知道涉及Equals()解决方法存在==!= ,但对关系运算符没有帮助)。

所以,有两个问题:

  1. 我们为什么要观察这种奇怪的行为? 什么让我们不能比较已知IComparable的genericstypes的值? 这难道不是以某种方式击败了通用约束的全部目的吗?
  2. 我如何解决这个问题,或者至less解决这个问题?

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

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

 value.CompareTo(_minimumValue) >= 0 

运算符重载的问题

不幸的是,接口不能包含重载操作符。 尝试在你的编译器中input:

 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); } 

我不知道为什么他们不允许这样做,但我猜测它使语言定义变得复杂,而且用户难以正确实施。

要么,要么devise师不喜欢滥用的可能性。 例如,想象一下在class MagicMrMeow上进行>=比较。 甚至在一个class Matrix<T> 。 结果对于这两个值有什么意义? 特别是当可能有歧义?

正式的解决方法

由于上述接口不合法,我们有IComparable<T>接口来解决这个问题。 它不实现运算符,并且只公开一个方法, 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可以为空,则当前的答案可能会失败。 使用类似这样的东西:

 Comparer<T>.Default.Compare(value, _minimumValue) >= 0 
 public bool IsInRange(T value) { return (value.CompareTo(_minimumValue) >= 0); } 

在使用IComparablegenerics时,所有小于/大于运算符都需要转换为对CompareTo的调用。 无论使用哪种算子,都要按照相同的顺序比较值,然后与零比较。 ( x <op> y变成x.CompareTo(y) <op> 0 ,其中<op>>>=等)

另外,我build议您使用的通用约束是where T : IComparable<T> 。 IComparable本身就意味着对象可以与任何东西进行比较,比较一个对象与其他同types的对象可能更合适。

而不是value >= _minimValue使用Comparer类:

 public bool IsInRange(T value ) { var result = Comparer<T>.Default.Compare(value, _minimumValue); if ( result >= 0 ) { return true; } else { return false; } } 

正如其他人所说,需要明确使用CompareTo方法。 一个人不能使用接口的原因是一个类可能实现了任意数量的接口,没有明确的排名。 假设试图计算expression式“a = foo + 5;” 当foo实现了六个接口时,所有这些接口定义了一个带有整数第二个参数的运算符“+” 哪个接口应该用于操作员?

类可以派生多个接口的事实使得接口非常强大。 不幸的是,这往往迫使人们更加明确地expression自己想要做什么。

IComparable只强制一个名为CompareTo()的函数。 所以你不能申请你提到的任何一个运营商