【问题标题】:C# Generic Collections, IComparer, IComparable and IEquatableC# 泛型集合、IComparer、IComparable 和 IEquatable
【发布时间】:2014-12-20 20:01:58
【问题描述】:

我正在开发一个 C# 项目,我大量使用接口和 System.Collections.Immutable 库。我希望在一个不可变集合中对我的一个接口的实现进行排序,ImmutableSortedSet<IMyInterface>

在 Java 中,这是实现Comparable<IMyInterface> 并覆盖equals 和hash 代码函数的简单问题。我在.net IComparable<IMyInterface> 中找到了一个类似的接口,但它警告实现者,如果他们选择实现该接口,那么他们还应该覆盖比较运算符(、=),以及实现@987654325 @。 IEquatable<T> 警告实现者,他们应该重写 equals 和 hash code 函数,以及 '==' 和 '!=' 运算符。

现在我正在重新考虑实现IComparable<T>,我不是在这里创建新的原始类型,我只是想为复杂的引用类型提供一种方便的排序算法。此外,在 C# 中似乎存在一定的问题,在接口级别覆盖运算符,因此我倾向于使用单独的 IComparer<IMyInterface> 实现。

真正让我大吃一惊的是:

IEquatable<T> 接口由泛型集合对象使用,例如 Dictionary<TKey, TValue>List<T>LinkedList<T>,在 ContainsIndexOfLastIndexOf 和 @ 等方法中测试相等性时987654336@。应该为可能存储在通用集合中的任何对象实现它。

这是否结合

如果你实现了IEquatable<T>,你还应该重写Object.Equals(Object)GetHashCode的基类实现,使它们的行为与IEquatable<T>.Equals方法的行为一致。如果您确实覆盖了Object.Equals(Object),那么在调用您的类上的静态Equals(System.Object, System.Object) 方法时也会调用您被覆盖的实现。此外,您应该重载 op_Equality 和 op_Inequality 运算符。这可确保所有相等性测试返回一致的结果。

意味着对于我想要存储在泛型集合中的任何类型,我都需要覆盖 '==' 和 '!=' 运算符??

【问题讨论】:

    标签: c# .net generics


    【解决方案1】:

    IComparable<T> 是为排序提供比较支持的首选机制。对于大多数类型来说,实现比较运算符的建议没有多大意义,而且它们也不能被泛型集合使用。您还应该实现IEquatable<T>,覆盖GetHashCode(),并覆盖object.Equals 以委托给IEquatable<T>.Equals

    一般来说,每当我实现IComparable<T> 时,我也会实现非泛型IComparable,但我会显式实现IComparable.CompareTo,使其通常是隐藏的。

    【讨论】:

    • 现在我很好奇为什么泛型集合不能使用重载的比较运算符,这是否与在编译时从泛型类中不知道泛型类型的值有关?
    • 没有办法知道所讨论的运算符实际上是为所有可能的类型参数实现的。
    【解决方案2】:

    正如您已经注意到的,如果您需要排序,您可以传递IComparer<T> 实现,而您的类型不必实现IComparable<T>。在某些情况下它更容易,在某些情况下它是唯一的方法,例如当您希望在不同情况下对相同类型进行不同排序时。在这种情况下,您可以只传递不同的 IComparer<T> 实现。

    关于IEquatable<T>的相关报价。对于大多数情况,覆盖 EqualsGetHashCode 就足够了。它将使您的类型与List<T>.Contains 和类似方法一起使用。它还允许您使用您的类型作为Dictionary<TKey, TValue> 中的键并将其存储在HashSet<T> 中。这是因为当没有指定比较器时,所有这些情况都使用EqualityComparer<T>.Default

    EqualityComparer<T>.Default 的工作方式可以在here 找到。如您所见,它会验证您的类型是否实现了IEquatable<T>,但如果它没有创建ObjectEqualityComparer<T> 的实例,它将仅使用EqualsGetHashCode 方法来验证相等性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2015-05-05
      • 1970-01-01
      相关资源
      最近更新 更多