分享
三行代码  ›  专栏  ›  技术社区  ›  TheBoxyBear

必须手动实现IEquatable<T>而不是IComparable<T>?[副本]

  •  0
  • TheBoxyBear  · 技术社区  · 6 天前

    我创建了一个自定义泛型列表类:

    class ComparableList<T> : IList<T>  where T : IComparable<T>
    

    对于泛型类型,我可以使用直接实现IComparable的类型,如:

    class MyComparableClass : IComparable<MyComparableClass>
    

    或者我可以使用从中继承的类型:

    class MyInheritedClass : MyComparableClass
    

    然后我决定 IEquatable<T> 更合适。

    所以我修改了list类的约束,并 MyComparableClass IComparable<MyComparableClass> IEquatable<MyComparableClass> .

    由于某种原因,我不能再使用 MyInheritedClass IEquatable<MyInheritedClass> IComparable<T> 突然间我又可以使用继承的类了。

    他们之间有什么不同 i可比较<T> 合理<T> 那规则就不一样了?

    2 回复  |  直到 6 天前
        1
  •  4
  •   Blindy    6 天前

    你的问题有点杂乱无章,很难理解,但如果我们只关注最后两段:

    出于某种原因,我不能再将MyInheritedClass用作自定义列表的泛型类型,除非手动使其实现IEquatable。我将list约束切换回IComparable,突然间我可以再次使用继承的类。

    IComparable和IEquatable之间有什么不同使得规则不同?

    协方差。 IComparable<T> 正如你写的,它实际上被定义为 IComparable<in T> IEquatable<T> 就是这样。

    这是有意义的,因为相等是一个非常强的语句,所以它的接口只接受与您测试的对象类型相同的对象类型(即没有协方差),而如果您愿意,您可以比较苹果和桔子,例如,一个比另一个更桔子,所以在这种情况下,有一个协变的可比较接口是有意义的。

        2
  •  0
  •   Sweeper    6 天前

    他们之间有什么不同 IComparable<T> IEquatable<T> 那规则就不一样了?

    IComparable<T> contravariant T

    public interface IComparable<in T> // note the word "in"
    

    鉴于 IEquatable<T> 不变量

    public interface IEquatable<T> // note the absence of "in"
    

    相反的意思是 IComaparable<Superclass> 是一种 IComparable<Subclass> .

    您的自定义列表要求 MyInheritedClass IComparable<MyInheritedClass> . MyInheritedClass类 IComparable<MyComparableClass> ,但这很好,因为 IComparable<MyComparableClass> 可以用作 IComaparable<MyInheritedClass>

    IEquatable 不是逆变的,所以你不能用 IEquatable<MyComparableClass> 作为一个 IEquatable<MyInheritedClass> .

    There is no technical reason why IEquatable isn't contravariant . 它在理论上可以是反变的,但设计师们决定反对它。有关更多信息,请参阅链接文章。