C#与IEnumerable T不同.与自定义IEqualityComparer [英] C# Distinct on IEnumerable<T> with custom IEqualityComparer

查看:143
本文介绍了C#与IEnumerable T不同.与自定义IEqualityComparer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这就是我想要做的.我正在使用LINQ to XML查询XML文件,这给了我IEnumerable >对象,其中T是我的村庄"类,并填充了此查询的结果.有些结果是重复的,所以我想对IEnumerable对象执行Distinct(),如下所示:

Here's what I'm trying to do. I'm querying an XML file using LINQ to XML, which gives me an IEnumerable<T> object, where T is my "Village" class, filled with the results of this query. Some results are duplicated, so I would like to perform a Distinct() on the IEnumerable object, like so:

public IEnumerable<Village> GetAllAlliances()
{
    try
    {
        IEnumerable<Village> alliances =
             from alliance in xmlDoc.Elements("Village")
             where alliance.Element("AllianceName").Value != String.Empty
             orderby alliance.Element("AllianceName").Value
             select new Village
             {
                 AllianceName = alliance.Element("AllianceName").Value
             };

        // TODO: make it work...
        return alliances.Distinct(new AllianceComparer());
    }
    catch (Exception ex)
    {
        throw new Exception("GetAllAlliances", ex);
    }
}

由于默认的比较器不适用于Village对象,因此我实现了一个自定义对象,如在AllianceComparer类中所示:

As the default comparer would not work for the Village object, I implemented a custom one, as seen here in the AllianceComparer class:

public class AllianceComparer : IEqualityComparer<Village>
{
    #region IEqualityComparer<Village> Members
    bool IEqualityComparer<Village>.Equals(Village x, Village y)
    {
        // Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) 
            return true;

        // Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        return x.AllianceName == y.AllianceName;
    }

    int IEqualityComparer<Village>.GetHashCode(Village obj)
    {
        return obj.GetHashCode();
    }
    #endregion
}

Distinct()方法不起作用,因为有或没有它,我得到的结果数完全相同.另一件事,我不知道这是否通常可行,但是我无法进入AllianceComparer.Equals()来查看可能是什么问题.
我已经在Internet上找到了这样的示例,但似乎无法使我的实现正常工作.

The Distinct() method doesn't work, as I have exactly the same number of results with or without it. Another thing, and I don't know if it's usually possible, but I cannot step into AllianceComparer.Equals() to see what could be the problem.
I've found examples of this on the Internet, but I can't seem to make my implementation work.

希望这里的人会发现这里可能出了什么问题! 预先感谢!

Hopefully, someone here might see what could be wrong here! Thanks in advance!

推荐答案

问题出在您的GetHashCode上.您应该对其进行更改以返回AllianceName的哈希码.

The problem is with your GetHashCode. You should alter it to return the hash code of AllianceName instead.

int IEqualityComparer<Village>.GetHashCode(Village obj)
{
    return obj.AllianceName.GetHashCode();
}

问题是,如果Equals返回true,则对象应具有相同的哈希码,而对于具有相同AllianceName的不同Village对象则不是这样.由于Distinct是通过内部构建哈希表来工作的,因此最终您将得到相等的对象,这些对象由于不同的哈希码而根本无法匹配.

The thing is, if Equals returns true, the objects should have the same hash code which is not the case for different Village objects with same AllianceName. Since Distinct works by building a hash table internally, you'll end up with equal objects that won't be matched at all due to different hash codes.

类似地,要比较两个文件,如果两个文件的哈希值不相同,则根本不需要检查文件本身.它们不同.否则,您将继续检查它们是否真的相同.这正是Distinct使用的哈希表的行为.

Similarly, to compare two files, if the hash of two files are not the same, you don't need to check the files themselves at all. They will be different. Otherwise, you'll continue to check to see if they are really the same or not. That's exactly what the hash table that Distinct uses behaves.

这篇关于C#与IEnumerable T不同.与自定义IEqualityComparer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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