T&GT ;,的IEqualityComparer< IEquatable℃之间的差异T>和压倒一切的.Equals()上的自定义对象集合使用LINQ是什么时候? [英] Differences between IEquatable<T>, IEqualityComparer<T>, and overriding .Equals() when using LINQ on a custom object collection?

查看:108
本文介绍了T&GT ;,的IEqualityComparer< IEquatable℃之间的差异T>和压倒一切的.Equals()上的自定义对象集合使用LINQ是什么时候?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用LINQ的。除()方法,比较自定义对象的两个集合时有些困难。

I'm having some difficulty using Linq's .Except() method when comparing two collections of a custom object.

我已经派生类我从对象和实施覆盖了等于() GetHash code()和运营商 == != 。我还创建了一个的CompareTo()方法。

I've derived my class from Object and implemented overrides for Equals(), GetHashCode(), and the operators == and !=. I've also created a CompareTo() method.

在我的两个集合,作为调试实验,我把第一个项目从每个列表(这是一式两份),并进行了比较如下:

In my two collections, as a debugging experiment, I took the first item from each list (which is a duplicate) and compared them as follows:

itemListA[0].Equals(itemListB[0]);     // true
itemListA[0] == itemListB[0];          // true
itemListA[0].CompareTo(itemListB[0]);  // 0

在这三种情况下,结果是我想要的。然而,当我使用Linq的除()方法,重复项目的的删除:

In all three cases, the result is as I wanted. However, when I use Linq's Except() method, the duplicate items are not removed:

List<myObject> newList = itemListA.Except(itemListB).ToList();

学习有关LINQ的如何做比较,我发现不同的是说我需要从 IEquatable&LT继承的方法(相冲突?); T&GT; 的IEqualityComparer&LT; T&GT;

我很困惑,因为当我继承,例如, IEquatable&LT; T&GT; ,我需要提供一个新的等于() 方法,从我已经覆盖不同的签名。我需要有两个这样的方法具有不同的签名,或者我应该不再获得我的类对象

I'm confused because when I inherit from, for example, IEquatable<T>, I am required to provide a new Equals() method with a different signature from what I've already overridden. Do I need to have two such methods with different signatures, or should I no longer derive my class from Object?

我的对象定义(简体)看起来是这样的:

My object definition (simplified) looks like this:

public class MyObject : Object
{
    public string Name {get; set;}
    public DateTime LastUpdate {get; set;}

    public int CompareTo(MyObject other)
    {
        // ...
    }

    public override bool Equals(object obj)
    {
        // allows some tolerance on LastUpdate
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + Name.GetHashCode();
            hash = hash * 23 + LastUpdate.GetHashCode();
            return hash;
        }
    }

    // Overrides for operators
}

我注意到,当我从继承 IEquatable&LT; T&GT; 我可以这样做,使用 IEquatable&LT;为MyObject&GT; IEquatable&LT;对象&gt; ;当我使用一个或另一个为要求的equals()签名更改。什么是推荐的方法是什么?

I noticed that when I inherit from IEquatable<T> I can do so using IEquatable<MyObject> or IEquatable<object>; the requirements for the Equals() signature change when I use one or the other. What is the recommended way?

我试图做到:

我希望能够使用Linq(DISTINCT /除外),以及标准相等运算符( == != ),而无需复制code。比较应该允许被视为两个对象相等,如果他们的名字是相同的的在 LASTUPDATE 属性是一个秒数内(用户指定)宽容。

I want to be able to use Linq (Distinct/Except) as well as the standard equality operators (== and !=) without duplicating code. The comparison should allow two objects to be considered equal if their name is identical and the LastUpdate property is within a number of seconds (user-specified) tolerance.

编辑:

显示 GetHash code() code。

推荐答案

这不要紧,你是否覆盖的Object.Equals 对象。 GetHash code ,实施 IEquatable ,或提供的IEqualityComparer 。所有这些的可以的工作,只是方式略有不同。

It doesn't matter whether you override object.Equals and object.GetHashCode, implement IEquatable, or provide an IEqualityComparer. All of them can work, just in slightly different ways.

1)重写等于 GetHash code 对象

这是基本的情况下,在感。它通常会工作,假设你在编辑的类型,以确保作为期望这两种方法的执行位置是。有没有错,在许多情况下只是这做的。

This is the base case, in a sense. It will generally work, assuming you're in a position to edit the type to ensure that the implementation of the two methods are as desired. There's nothing wrong with doing just this in many cases.

2)实施 IEquatable

这里的关键是,你可以(也应该)落实 IEquatable&LT; YourTypeHere&GT; 。这和#1之间的主要区别是,你必须为等于法强类型,而不是仅仅有它使用对象。这是既为方便程序员(增加类型安全)更好,也意味着任何值类型将不被加框,所以这可以提高自定义结构的性能。如果你这样做,你应该pretty多少总是做它的除#1,的而不是替代。具有等于此处方法在功能上不同于的Object.Equals 将是...坏。不这样做。

The key point here is that you can (and should) implement IEquatable<YourTypeHere>. The key difference between this and #1 is that you have strong typing for the Equals method, rather than just having it use object. This is both better for convenience to the programmer (added type safety) and also means that any value types won't be boxed, so this can improve performance for custom structs. If you do this you should pretty much always do it in addition to #1, not instead of. Having the Equals method here differ in functionality from object.Equals would be...bad. Don't do that.

3)实施的IEqualityComparer

这是从第一两个完全不同的。这里的想法是,对象是没有得到它自己的哈希值code,或者看它是否等于别的东西。这种方法的一点是,的对象不知道如何正确地得到它的hash或者看它是否等于别的的。也许是因为你不控制的类型(即第三方库)的code和他们没有打扰重写的行为,或者他们没有覆盖它,但你只是想自己独特的定义平等在此特定上下文。

This is entirely different from the first two. The idea here is that the object isn't getting it's own hash code, or seeing if it's equal to something else. The point of this approach is that an object doesn't know how to properly get it's hash or see if it's equal to something else. Perhaps it's because you don't control the code of the type (i.e. a 3rd party library) and they didn't bother to override the behavior, or perhaps they did override it but you just want your own unique definition of "equality" in this particular context.

在这种情况下,建立一个完全独立的比较器对象,它发生在两个不同的对象并通知您它们是否相等或没有,或什么人对象的哈希code是。当使用这种解决方案的也无所谓什么等于 GetHash code 方法做该类型本身的,你不会使用它。

In this case you create an entirely separate "comparer" object that takes in two different objects and informs you of whether they are equal or not, or what the hash code of one object is. When using this solution it doesn't matter what the Equals or GetHashCode methods do in the type itself, you won't use it.

请注意,所有这一切是从 == 运营商,这是它自己的野兽完全无关。

Note that all of this is entirely unrelated from the == operator, which is its own beast.

这篇关于T&GT ;,的IEqualityComparer&LT; IEquatable℃之间的差异T&gt;和压倒一切的.Equals()上的自定义对象集合使用LINQ是什么时候?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆