从实现IComparable的东西继承时,C#BinarySearch会中断<;T>;?
在.NET中,如果您试图搜索的项继承自IComparable,而不是直接实现它,则BinarySearch算法(在列表、数组等中)似乎会失败:从实现IComparable的东西继承时,C#BinarySearch会中断<;T>;?,c#,generics,inheritance,sorting,interface,C#,Generics,Inheritance,Sorting,Interface,在.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,
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."
List foo=new List();//B继承自A,后者实现了IComparable
foo.Add(新的B());
foo.BinarySearch(新的B());//InvalidOperationException,“无法比较数组中的两个元素。”
其中:
public abstract class A : IComparable<A>
{
public int x;
public int CompareTo(A other)
{
return x.CompareTo(other.x);
}
}
public class B : A {}
公共抽象类A:IComparable
{
公共int x;
公共整数比较(A其他)
{
返回x.CompareTo(其他x);
}
}
公共B类:A{}
有办法解决这个问题吗?在B类中实现CompareTo(B-other)似乎不起作用。文档非常清楚地说明了这一点: 检查类型T是否实现IComparable泛型接口并使用该实现(如果可用)。如果不是,Comparer.Default将检查类型T是否实现IComparable接口。如果类型T未实现任何一个接口,则Comparer.Default会抛出InvalidOperationException 因此,一个简单的解决方案是实现非通用接口
IComparable
将
CompareTo(B other)
添加到(B other)将对您有效,只要您还实现了IComparable
——您可能忘记了这一点
一个有趣的解决方案是使用C#4编译代码,它在C#4中运行时没有任何错误。C#4引入了通用协方差:
public interface IComparable
vspublic interface IComparable
,并且发布的代码按预期工作。对,所以问题是它试图看看类B
是否实现了IComparable
,但它没有实现,因为它实际上实现了IComparable
,然后尝试IComparable
,然后放弃。正如Kobi指出的,实现非泛型的IComparable将解决这个问题。尽管上述答案对于4.0之前的.net版本是正确的,但值得注意的是.net 4.0对IComparable的定义是协变的,这意味着如果类实现IComparable,但没有显式实现IComparable,if IComparable的实现将被视为if IComparable的实现
请注意,这不适用于IEquatable,但由于派生类型无论如何都不应该实现IEquatable,所以这不应该是一个问题
还请注意,与逻辑上绑定为实现与Object.Equals非常相似的语义的IEquatable不同(因为GetHashCode实现返回的对象必须比较不相等),在许多情况下,IComparable应该逻辑上返回相等,即使IComparable应该比较不相等(在这种情况下,派生类型通常应实现IComparable,但不应实现重新实现IComparable。请注意,如果IComparable.Compare返回零,则这并不意味着对象相等,而只是意味着两个对象的排名都不高于另一个。此代码在我的C#compiler@Stewart-你可能正在使用g C#4。@Kobi-哎呀,完全正确。我忘了这已经改变了,问题没有提到版本。