在.NET中,如果您尝试搜索的项目从IComparable继承而不是直接实现,则BinarySearch算法(在列表,数组等中)似乎会失败:
List<B> foo = new List<B>(); // B inherits from A, which implements IComparable<A>
foo.Add(new B());
foo.BinarySearch(new B()); // InvalidOperationException, "Failed to compare two elements in the array."
其中:
public abstract class A : IComparable<A>
{
public int x;
public int CompareTo(A other)
{
return x.CompareTo(other.x);
}
}
public class B : A {}
有解决方法吗?在B类中实现CompareTo(B other)似乎不起作用。
答案 0 :(得分:7)
文档清楚地说明了这一点:
检查类型T是否实现IComparable通用接口并使用该实现(如果可用)。如果不是,Comparer.Default检查类型T是否实现IComparable接口。如果类型T没有实现任何一个接口,Comparer.Default会抛出InvalidOperationException。
因此,一个简单的解决方案是实现非通用接口IComparable
添加CompareTo(B other)
将为您工作,只要您同时实施IComparable<B>
- 您可能忘记了这一点。
一个有趣的解决方案是使用C#4编译代码,它运行时没有任何错误。 C#4引入了通用协方差:public interface IComparable<in T>
vs public interface IComparable<T>
,发布的代码按预期工作。
答案 1 :(得分:1)
是的,所以问题是它试图查看class B
是否实现了IComparable<B>
,它没有,因为它实际上实现了IComparable<A>
,然后尝试IComparable
然后放弃。正如Kobi指出的那样,实现非通用IComparable
将解决这个问题。
答案 2 :(得分:0)
虽然上述答案对于4.0之前的.net版本是正确的,但值得注意的是.Net 4.0定义了IComparable&lt; T&gt; covariantly,这意味着如果类实现IComparable&lt; BaseType&gt;但是没有明确地实现IComparable&lt; DerivedType&gt;,IComparable&lt; BaseType&gt;的实现。将被视为IComparable&lt; DerivedType&gt;。
的实现注意,这不适用于IEquatable&lt; T&gt;,但由于可派生类型不应实现IEquatable&lt; T&gt;。无论如何,这应该不是问题。
另请注意,与IEquatable&lt; T&gt;不同。逻辑上绑定以实现与Object.Equals非常相似的语义(因为GetHashCode实现返回不等的对象必须比较不相等),有许多情况下IComparable&lt; BaseType&gt;即使IComparable&lt; DerivedType&gt;也应该在逻辑上返回相等的应该比较不相等(在这种情况下,派生类型通常应该实现IComparable&lt; DerivedType&gt;但不能重新实现IComparable&lt; BaseType&gt;。注意,如果IComparable&lt; T&gt; .Compare返回零,那并不意味着对象相等,但仅仅是没有一个明确地排在另一个之上。