What is the difference between IEqualityComparer and IEquatable?

前端 未结 5 1701
不思量自难忘°
不思量自难忘° 2020-11-30 19:45

I want to understand the scenarios where IEqualityComparer and IEquatable should be used. The MSDN documentation for both looks very similar.

5条回答
  •  粉色の甜心
    2020-11-30 20:16

    When deciding whether to use IEquatable or IEqualityComparer, one could ask:

    Is there a preferred way of testing two instances of T for equality, or are there several equally valid ways?

    • If there is only one way of testing two instances of T for equality, or if one of several methods is preferred, then IEquatable would be the right choice: This interface is supposed to be implemented only by T itself, so that one instance of T has internal knowledge of how to compare itself to another instance of T.

    • On the other hand, if there are several equally reasonable methods of comparing two Ts for equality, IEqualityComparer would seem more appropriate: This interface is not meant to be implemented by T itself, but by other "external" classes. Therefore, when testing two instances of T for equality, because T has no internal understanding of equality, you will have to make an explicit choice of a IEqualityComparer instance which performs the test according to your specific requirements.

    Example:

    Let's consider these two types (which are supposed to have value semantics):

    interface IIntPoint : IEquatable
    {
        int X { get; }
        int Y { get; }
    }
    
    interface IDoublePoint  // does not inherit IEquatable; see below.
    {
        double X { get; }
        double Y { get; }
    }
    

    Why would only one of these types inherit IEquatable<>, but not the other?

    In theory, there is only one sensible way of comparing two instances of either type: They are equal if the X and Y properties in both instances are equal. According to this thinking, both types should implement IEquatable<>, because it doesn't seem likely that there are other meaningful ways of doing an equality test.

    The issue here is that comparing floating-point numbers for equality might not work as expected, due to minute rounding errors. There are different methods of comparing floating-point numbers for near-equality, each with specific advantages and trade-offs, and you might want to be able to choose yourself which method is appropriate.

    sealed class DoublePointNearEqualityComparerByTolerance : IEqualityComparer
    {
        public DoublePointNearEqualityComparerByTolerance(double tolerance) { … }
        …
        public bool Equals(IDoublePoint a, IDoublePoint b)
        {
            return Math.Abs(a.X - b.X) <= tolerance  &&  Math.Abs(a.Y - b.Y) <= tolerance;
        }
        …
    }
    

    Note that the page I linked to (above) explicitly states that this test for near-equality has some weaknesses. Since this is a IEqualityComparer implementation, you can simply swap it out if it's not good enough for your purposes.

提交回复
热议问题