【问题标题】:What's the difference between IComparable & IEquatable interfaces?IComparable 和 IEquatable 接口有什么区别?
【发布时间】:2011-01-25 11:45:23
【问题描述】:

这两个接口似乎都比较对象是否相等,那么它们之间的主要区别是什么?

【问题讨论】:

    标签: c# interface icomparable iequatable


    【解决方案1】:

    IEquatable 测试两个对象是否相等。

    IComparable 对正在比较的对象进行总排序。

    例如,IEquatable 会告诉您 5 不等于 7。IComparable 会告诉您 5 在 7 之前。

    【讨论】:

      【解决方案2】:

      IEquatable<T> 表示平等。

      IComparable<T>订购。

      【讨论】:

        【解决方案3】:

        除了 Greg D 的回答:

        您可以在不实现IEquatable 的情况下实现IComparable,而不实现部分排序有意义的类,并且您非常肯定希望消费者仅仅因为CompareTo() 返回零而推断出这一点,这不 暗示对象是相等的(除了排序目的之外)。

        【讨论】:

        • 这听起来更像是一个特殊情况的比较器,而不是一个正确实现IComparable 的对象。你能想出一个有意义的例子,CompareTo(…) == 0 not 是否意味着平等?我当然不能。事实上,接口契约(根据 MSDN)要求CompareTo(…) == 0 意味着平等。说白了,在你这种情况下,使用一个特殊的Comparator对象,不要实现IComparable
        • @Konrad - 我确实指出了几个警告 - 该类型没有实现 IEquatable (很明显,发起者不想包含相等测试),并且 CompareTo 结果用于排序, not 来评估相等性。您还会遇到与平等相关的问题(参考、价值、忽略“任意”属性 - 出于 IComparable 的目的,一本 500 页的蓝皮书可能与一本 500 页的红皮书“相等”)
        • 你的最后一句话是错误的,这是我想指出的具体错误:IComparable 在这里完全不合适。你得到的是一个非常特定的顺序,它只适用于一种特殊情况。对于这种情况,实现一般的IComparable 是错误的。这就是IComparers 的用途。例如,无法对人员进行有意义的排序。但他们可以根据他们的薪水、鞋码、雀斑数量或体重来订购。因此,我们将为所有这些情况实施不同的IComparers。
        • @Konrad Rudolph:像“ScheduledEvent”类这样的东西,它应该在某个特定时间做“某事”?该类型的语义意味着一个非常强的自然语义排序,该顺序基于动作应该发生的时间,但是很容易同时发生不同的事件。可能需要使用手动指定的 IComparer,但我认为在类中内置一个比较器会更方便。
        • @supercat 方便很重要,但不是一切。正确性(如逻辑一致性)更为重要,静态类型系统是验证这种逻辑一致性的重要工具。通过违反您实现的接口的文档约定,您正在颠覆类型系统。这不是一个好主意,我永远不会推荐它。在这种情况下使用外部比较器。
        【解决方案4】:

        MSDN Page for IEquatable 所述:

        IComparable 接口定义 CompareTo 方法,它确定 的实例的排序顺序 实现类型。 IEquatable 接口定义了Equals方法, 这决定了平等 实现类型的实例。

        EqualsCompareTo

        【讨论】:

          【解决方案5】:

          IComparable <T> 定义了一种特定于类型的比较方法,可用于对对象进行排序或排序。

          IEquatable <T> 定义了一个通用方法,可用于实现确定相等性。


          假设你有 Person 类

          public class Person
          {
              public string Name { get; set; }
              public int Age { get; set; }
          }
          
          Person p1 = new Person() { Name = "Person 1", Age = 34 };
          Person p2 = new Person() { Name = "Person 2", Age = 31 };
          Person p3 = new Person() { Name = "Person 3", Age = 33 };
          Person p4 = new Person() { Name = "Person 4", Age = 26 };
          
          List<Person> people = new List<Person> { p1, p2, p3, p4 };
          

          要对这些对象进行排序,您可以使用people.Sort();

          但这会引发异常。

          框架不知道如何对这些对象进行排序。你需要告诉如何排序实现IComparable 接口。

          public class Person : IComparable
          {
              public string Name { get; set; }
              public int Age { get; set; }
          
              public int CompareTo(object obj)
              {
                  Person otherPerson = obj as Person;
                  if (otherPerson == null)
                  {
                      throw new ArgumentNullException();
                  }
                  else
                  {
                      return Age.CompareTo(otherPerson.Age);
                  }
              }
          }
          

          这将使用Sort() 方法正确排序数组。


          接下来比较两个对象可以使用Equals()方法。

          var newPerson = new Person() { Name = "Person 1", Age = 34 };
          var newPersonIsPerson1 = newPerson.Equals(p1);
          

          这将返回false,因为Equals 方法不知道如何比较两个对象。因此你需要实现IEquatable 接口并告诉框架如何进行比较。扩展上一个示例,它看起来像这样。

          public class Person : IComparable, IEquatable<Person>
          {
              //Some code hidden
          
              public bool Equals(Person other)
              {
                  if (Age == other.Age && Name == other.Name)
                  {
                      return true;
                  }
                  else
                  {
                      return false;
                  }
              }
          }
          

          【讨论】:

          • 感谢您的精彩解释。问题:为什么IEquatable 使用通用的&lt;Person&gt;IComparable 没有?
          猜你喜欢
          • 1970-01-01
          • 2011-02-13
          • 2019-10-16
          • 1970-01-01
          • 1970-01-01
          • 2018-01-06
          • 2010-12-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多