C# IEqualityComparer<T> 和 IEquatable<T> 有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9316918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 06:52:03  来源:igfitidea点击:

What is the difference between IEqualityComparer<T> and IEquatable<T>?

c#.netequalsiequalitycompareriequatable

提问by Tilak

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

我想了解应该使用IEqualityComparer<T>IEquatable<T>使用的场景。两者的 MSDN 文档看起来非常相似。

采纳答案by Justin Niessner

IEqualityComparer<T>is an interface for an object that performs the comparison on two objects of the type T.

IEqualityComparer<T>是一个对象的接口,它对类型为 的两个对象执行比较T

IEquatable<T>is for an object of type Tso that it can compare itself to another.

IEquatable<T>用于类型的对象,T以便它可以将自己与另一个对象进行比较。

回答by Matt Ball

One compares two Ts. The other can compare itself to other Ts. Usually, you'll only need to use one at at time, not both.

一个比较两个Ts。另一个可以将自己与其他Ts进行比较。通常,您一次只需要使用一个,而不是两个都使用。

回答by Chris Shain

IEqualityComparer is for use when the equality of two objects is externally implemented, e.g. if you wanted to define a comparer for two types that you did not have the source for, or for cases where equality between two things only makes sense in some limited context.

IEqualityComparer 用于在外部实现两个对象的相等性时使用,例如,如果您想为没有源的两种类型定义比较器,或者用于两个事物之间的相等性仅在某些有限上下文中有意义的情况。

IEquatable is for the object itself (the one being compared for equality) to implement.

IEquatable 是为对象本身(被比较为相等的对象)来实现的。

回答by nawfal

You have already got the basic definition of what they are. In short, if you implement IEquatable<T>on class T, the Equalsmethod on an object of type Ttells you if the object itself (the one being tested for equality) is equal to another instance of the same type T. Whereas, IEqualityComparer<T>is for testing the equality of any two instances of T, typically outside the scope of the instances of T.

您已经获得了它们的基本定义。简而言之,如果您IEquatable<T>在 class上实现T,则Equalstype 对象上的方法会T告诉您该对象本身(正在测试是否相等的对象)是否等于相同类型的另一个实例T。而,IEqualityComparer<T>用于测试 的任意两个实例的相等性T,通常在 的实例范围之外T

As to what they are forcan be confusing at first. From the definition it should be clear that hence IEquatable<T>(defined in the class Titself) should be the de facto standard to represent uniqueness of its objects/instances. HashSet<T>, Dictionary<T, U>(considering GetHashCodeis overridden as well), Containson List<T>etc make use of this. Implementing IEqualityComparer<T>on Tdoesn't help the above mentioned general cases. Subsequently, there is little value for implementing IEquatable<T>on any other class other than T. This:

至于它们的用途,一开始可能会令人困惑。从定义中应该很清楚,因此IEquatable<T>(在类T本身中定义)应该是表示其对象/实例唯一性的事实上的标准。HashSet<T>, Dictionary<T, U>(考虑GetHashCode也被覆盖),ContainsonList<T>等利用这个。实施IEqualityComparer<T>T上述一般情况没有帮助。随后,在IEquatable<T>除 之外的任何其他类上实现几乎没有价值T。这个:

class MyClass : IEquatable<T>

rarely makes sense.

很少有道理。

On the other hand

另一方面

class T : IEquatable<T>
{
    //override ==, !=, GetHashCode and non generic Equals as well

    public bool Equals(T other)
    {
        //....
    }
}

is how it should be done.

应该怎么做。

IEqualityComparer<T>can be useful when you require a custom validation of equality, but not as a general rule. For instance, in a class of Personat some point you might require to test equality of two people based on their age. In that case you can do:

IEqualityComparer<T>当您需要自定义相等性验证时可能很有用,但不是一般规则。例如,在Person某个时候,您可能需要根据年龄测试两个人的平等程度。在这种情况下,你可以这样做:

class Person
{
    public int Age;
}

class AgeEqualityTester : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return x.Age == y.Age;
    }

    public int GetHashCode(Person obj)
    {
        return obj.Age.GetHashCode;
    }
}

To test them, try

要测试它们,请尝试

var people = new Person[] { new Person { age = 23 } };
Person p = new Person() { age = 23 };

print people.Contains(p); //false;
print people.Contains(p, new AgeEqualityTester()); //true

Similarly IEqualityComparer<T>on Tdoesn't make sense.

同样IEqualityComparer<T>T没有意义。

class Person : IEqualityComparer<Person>

True this works, but doesn't look good to eyes and defeats logic.

确实这有效,但看起来不好看并且不符合逻辑。

Usually what you need is IEquatable<T>. Also ideally you can have only one IEquatable<T>while multiple IEqualityComparer<T>is possible based on different criteria.

通常你需要的是IEquatable<T>. 理想情况下,您只能拥有一个,IEquatable<T>IEqualityComparer<T>根据不同的标准可能有多个。

The IEqualityComparer<T>and IEquatable<T>are exactly analogous to Comparer<T>and IComparable<T>which are used for comparison purposes rather than equating; a good thread herewhere I wrote the same answer :)

IEqualityComparer<T>IEquatable<T>是完全类似Comparer<T>IComparable<T>其用于比较目的,而不是等同; 一个很好的线程这里我写了相同的答案:)

回答by stakx - no longer contributing

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

在决定是否使用IEquatable<T>或 时IEqualityComparer<T>,可以问:

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

是否有测试两个实例T是否相等的首选方法,或者是否有几种同样有效的方法?

  • If there is only one way of testing two instances of Tfor equality, or if one of several methods is preferred, then IEquatable<T>would be the right choice: This interface is supposed to be implemented only by Titself, so that one instance of Thas 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<T>would seem more appropriate: This interface is not meant to be implemented by Titself, but by other "external" classes. Therefore, when testing two instances of Tfor equality, because Thas no internal understanding of equality, you will have to make an explicit choice of a IEqualityComparer<T>instance which performs the test according to your specific requirements.

  • 如果只有一种方法可以测试两个 的实例T是否相等,或者首选几种方法中的一种,那么IEquatable<T>这将是正确的选择:该接口应该仅由T自身实现,因此 的一个实例T具有内部知识如何将自己与T.

  • 另一方面,如果有几个同样合理的方法来比较两个Ts 是否相等,IEqualityComparer<T>似乎更合适:这个接口不是由T它自己实现的,而是由其他“外部”类实现的。因此,在测试两个Tfor 相等的实例时,由于对相等T没有内部理解,您将不得不IEqualityComparer<T>根据您的特定要求明确选择执行测试的实例。

Example:

例子:

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

让我们考虑这两种类型(它们应该具有值语义):

interface IIntPoint : IEquatable<IIntPoint>
{
    int X { get; }
    int Y { get; }
}

interface IDoublePoint  // does not inherit IEquatable<IDoublePoint>; see below.
{
    double X { get; }
    double Y { get; }
}

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

为什么这些类型中只有一种会继承IEquatable<>而另一种不会?

In theory, there is only one sensible way of comparing two instances of either type: They are equal if the Xand Yproperties 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.

理论上,比较任一类型的两个实例只有一种合理的方法:如果两个实例中的XY属性相等,则它们相等。根据这种想法,两种类型都应该实现IEquatable<>,因为似乎不可能有其他有意义的方法来进行相等性测试。

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<IDoublePoint>
{
    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<T>implementation, you can simply swap it out if it's not good enough for your purposes.

请注意,我链接到(上面)的页面明确指出,这个近似相等的测试有一些弱点。由于这是一个IEqualityComparer<T>实现,如果它对您的目的来说不够好,您可以简单地将其换掉。