【问题标题】:C# BinarySearch breaks when inheriting from something that implements IComparable<T>?从实现 IComparable<T> 的东西继承时,C# BinarySearch 会中断?
【发布时间】:2010-05-02 04:45:17
【问题描述】:

在 .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) 似乎不起作用。

【问题讨论】:

  • 这段代码在我的 C# 编译器上运行得很好
  • @Stewart - 你可能正在使用 C# 4。
  • @Kobi - 哎呀,完全正确。我忘了这已经改变了,问题没有提到版本。

标签: c# generics inheritance sorting interface


【解决方案1】:

文档说明了这一点:

检查类型 T 是否实现 IComparable 泛型接口并使用该实现(如果可用)。如果没有,Comparer.Default 检查类型 T 是否实现了 IComparable 接口。如果类型 T 没有实现任何一个接口,Comparer.Default 会抛出 InvalidOperationException。

所以,一个简单的解决方案是实现非泛型接口IComparable。
添加CompareTo(B other) 将为您工作,只要您还实现IComparable&lt;B&gt; - 您可能忘记了这一点。

一个有趣的解决方案是使用 C# 4 编译代码,它运行时没有任何错误。 C# 4 引入了通用协方差:public interface IComparable&lt;in T&gt; 与 public interface IComparable&lt;T&gt;,并且发布的代码按预期工作。

【讨论】:

    【解决方案2】:

    对,所以问题是它尝试查看class B 是否实现IComparable&lt;B&gt;,它没有实现,因为它实际上实现了IComparable&lt;A&gt;,然后尝试IComparable 然后放弃。正如 Kobi 指出的那样,实现非泛型 IComparable 将解决这个问题。

    【讨论】:

      【解决方案3】:

      虽然上述答案对于 .net 4.0 之前的版本是正确的,但值得注意的是 .Net 4.0 定义了 IComparable 协变,这意味着如果类实现了 IComparable 但没有显式实现 IComparable ,如果 IComparable 的实现将被视为 IComparable 的实现。

      请注意,这不适用于 IEquatable,但由于可派生类型无论如何都不应该实现 IEquatable,这应该不是问题。

      还请注意,与 IEquatable 不同,IEquatable 在逻辑上必须实现与 Object.Equals 非常相似的语义(因为 GetHashCode 实现返回不相等的对象必须比较不相等),在许多情况下 IComparable 应该在逻辑上即使 IComparable 应该比较不相等也返回相等(在这种情况下,派生类型通常应该实现 IComparable 但不重新实现 IComparable。请注意,如果 IComparable.Compare 返回零,这并不意味着对象是相等的,但只是没有一个明确地排在另一个之上。

      【讨论】:

        猜你喜欢
        • 2020-01-23
        • 1970-01-01
        • 1970-01-01
        • 2012-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多