gst*_*ken 70 .net c# generics icomparable
如何比较泛型类型的值?
我把它减少到最小的样本:
public class Foo<T> where T : IComparable
{
private T _minimumValue = default(T);
public bool IsInRange(T value)
{
return (value >= _minimumValue); // <-- Error here
}
}
Run Code Online (Sandbox Code Playgroud)
错误是:
运算符'> ='不能应用于'T'和'T'类型的操作数.
到底怎么回事!?T已被约束到IComparable,甚至它限制值类型(的时候where T: struct),我们仍然不能将任何运营商<,>,<=,>=,==或!=.(我知道,涉及到解决方法Equals()的存在==和!=,但它并不能帮助对于关系运算符).
那么,有两个问题:
IComparable?它不是以某种方式打败了通用约束的整个目的吗?(我意识到已经有一些问题与这个看似简单的问题有关 - 但没有一个线程能给出详尽或可行的答案,所以在这里.)
fae*_*ter 87
IComparable不会使>=操作员超载.你应该用
value.CompareTo(_minimumValue) >= 0
Run Code Online (Sandbox Code Playgroud)
Mer*_*ham 31
运算符重载问题
不幸的是,接口不能包含重载的运算符.尝试在编译器中输入:
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);
}
Run Code Online (Sandbox Code Playgroud)
我不知道为什么他们不允许这样做,但我猜它使语言定义变得复杂,并且用户很难正确实现.
要不然,或者设计师不喜欢滥用的可能性.例如,想象一下做一个>=比较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.
Run Code Online (Sandbox Code Playgroud)
使用解决方法
为了做相同的事情value >= _minimumValue,你必须写:
value.CompareTo(_minimumValue) >= 0
Run Code Online (Sandbox Code Playgroud)
Pet*_*erg 25
如果value可以为null,则当前答案可能会失败.使用这样的东西代替:
Comparer<T>.Default.Compare(value, _minimumValue) >= 0
Run Code Online (Sandbox Code Playgroud)
public bool IsInRange(T value)
{
return (value.CompareTo(_minimumValue) >= 0);
}
Run Code Online (Sandbox Code Playgroud)
使用IComparable泛型时,所有小于/大于运算符的都需要转换为对CompareTo的调用.无论您使用哪种运算符,都要保持以相同顺序进行比较的值,并与零进行比较.(x <op> y变x.CompareTo(y) <op> 0,其中<op>是>,>=等)
另外,我建议您使用的通用约束where T : IComparable<T>.IComparable本身意味着可以将对象与任何东西进行比较,将对象与相同类型的其他对象进行比较可能更合适.