简体   繁体   English

实现 IEqualityComparer

[英]Implement IEqualityComparer

I would like to get distinct objects from a list.我想从列表中获取不同的对象。 I tried to implement IEqualityComparer but wasn't successful.我试图实现IEqualityComparer但没有成功。 Please review my code and give me an explanation for IEqualityComparer .请查看我的代码并为我解释IEqualityComparer

public class Message
{
    public int x { get; set; }
    public string y { get; set; }
    public string z { get; set; }
    public string w { get; set; }
}

public class MessageComparer : IEqualityComparer<Message>
{
    public bool Equals(Message x, Message y)
    {
        if (Object.ReferenceEquals(x, y)) return true;

        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        if (x.x == y.x && x.y == y.y && x.z == y.z && x.w == y.w)
        {
            return true;
        }

        return false;
    }

    public int GetHashCode(Message number)
    {
        // if (Object.ReferenceEquals(number, null)) return 0;
        int hashX = number.x.GetHashCode();
        int hashY = number.y == null ? 0 : number.y.GetHashCode();
        int hashZ = number.z == null ? 0 : number.z.GetHashCode();
        int hashW = number.w == null ? 0 : number.w.GetHashCode();

        return hashX ^ hashY ^ hashZ ^ hashW;           
    }
}

This is my List with Message objects:这是我的Message对象List

Message m1 = new Message();
m1.x = 1;
m1.y = "A";
m1.z = "B";
m1.w = "C";

Message m2 = new Message();
m2.x = 1;
m2.y = "A";
m2.z = "B";
m2.w = "C";

Message m3 = new Message();
m3.x = 1;
m3.y = "A";
m3.z = "B";
m3.w = "C";

Message m4 = new Message();
m4.x = 2;
m4.y = "A";
m4.z = "B";
m4.w = "C";

Message m5 = new Message();
m5.x = 3;
m5.y = "W";
m5.z = "D";
m5.w = "C";

Message m6 = new Message();
m6.x = 4;
m6.y = "S";
m6.z = "F";
m6.w = "R";

List<Message> collection = new List<Message>();
collection.Add(m1);
collection.Add(m2);
collection.Add(m3);
collection.Add(m4);
collection.Add(m5);

collection.Distinct(new MessageComparer());

When I call the Distinct() method, the number of elements in collection are the same.当我调用Distinct()方法时, collection中的元素数量是相同的。

Try this:尝试这个:

var distinct = collection.Distinct(new MessageComparer());

Then use distinct for anything after that.然后对之后的任何内容使用distinct

It looks like you're forgetting the immutable nature of IEnumerable<> .看起来您忘记了IEnumerable<>的不可变性质。 None of the LINQ methods actually change the original variable.没有任何 LINQ 方法实际上会更改原始变量。 Rather, they return IEnuerable<T> s which contain the result of the expression.相反,它们返回包含表达式结果的IEnuerable<T> s。 For example, let's consider a simple List<string> original with the contents { "a", "a", "b", "c" } .例如,让我们考虑一个简单的List<string> original内容,其内容为{ "a", "a", "b", "c" }

Now, let's call original.Add("d");现在,让我们调用original.Add("d"); . . That method has no return value (it's void ).该方法没有返回值(它是void )。 But if we then print out the contents of original , we will see { "a", "a", "b", "c", "d" } .但是如果我们打印出original的内容,我们会看到{ "a", "a", "b", "c", "d" }

On the other hand, let's now call original.Skip(1) .另一方面,让我们现在调用original.Skip(1) This method does have a return value, one of type IEnumerable<string> .此方法确实有一个返回值,即IEnumerable<string>类型之一。 It is a LINQ expression, and performs no side-effecting actions on the original collection.它是一个 LINQ 表达式,不会对原始集合执行任何副作用。 Thus, if we call that and look at original , we will see { "a", "a", "b", "c", "d" } .因此,如果我们调用它并查看original ,我们将看到{ "a", "a", "b", "c", "d" } However, the result from the method will be { "a", "b", "c", "d" } .但是,该方法的结果将是{ "a", "b", "c", "d" } As you can see, the result skips one element.如您所见,结果跳过了一个元素。

This is because LINQ methods accept IEnumerable<T> as a parameter.这是因为 LINQ 方法接受IEnumerable<T>作为参数。 Consequently, they have no concept of the implementation of the original list.因此,他们没有实现原始列表的概念。 You could be passing, via extension method, a ReadOnlyCollection and they would still be able to evaluate through it.您可以通过扩展方法传递ReadOnlyCollection ,他们仍然可以通过它进行评估。 They cannot, then, alter the original collection, because the original collection could be written in any number of ways.然后,他们无法更改原始集合,因为原始集合可以以多种方式编写。

All that, but in table form.所有这些,但以表格形式。 Each lines starts with the original { "a", "a", "b", "c" } :每行都以原始{ "a", "a", "b", "c" }开头:

Context     Example function    Immutable?    Returned Value     Collection after calling
Collection  Add("d")            No            (void)             { "a", "a", "b", "c", "d" }:
LINQ        Skip(1)             Yes           { "a", "b", "c" }  { "a", "a", "b", "c" }:

IEqualityComparer is an interface which is used to find whether an object is equal or not. IEqualityComparer是一个用于判断对象是否相等的接口。 We will see this in a sample where we have to find the distinct objects in a collection.我们将在一个示例中看到这一点,我们必须在一个集合中找到不同的对象。 This interface will implement the method Equals(T obj1,T obj2) .该接口将实现Equals(T obj1,T obj2)

abstract public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { set; get; }
}

public enum SortType
{
    ByID,
    BySalary
}

public class EmployeeDistinctEquality : IEqualityComparer<Employee>
{
    public EmployeeDistinctEquality()
    {

    }

    public bool Equals(Employee x, Employee y)
    {
        if (x == null && y == null)
            return true;
        else if (x == null || y == null)
            return false;
        else if (x.Id == y.Id)
            return true;
        else
            return false;
    }

    public int GetHashCode(Employee obj)
    {
        return obj.Id.GetHashCode();
    }
}

Refer to this link for more detailed information:有关更多详细信息,请参阅此链接:

http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

You don't need to implement IEqualityComparer :您不需要实现IEqualityComparer

public class Message
{
    protected bool Equals(Message other)
    {
        return string.Equals(x, other.x) && string.Equals(y, other.y) && string.Equals(z, other.z) && string.Equals(w, other.w);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Message) obj);
    }

    public override int GetHashCode()
    {
        unchecked //Ignores overflows that can (should) occur
        {
            var hashCode = x;
            hashCode = (hashCode*397) ^ (y != null ? y.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (z != null ? z.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (w != null ? w.GetHashCode() : 0);
            return hashCode;
        }
    }

    public int x { get; set; }
    public string y { get; set; }
    public string z { get; set; }
    public string w { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM