C#与IEnumerable <T>的区别在于自定义IEqualityComparer

Fue*_*led 52 c# ienumerable distinct linq-to-xml

这就是我想要做的.我正在使用LINQ to XML查询XML文件,它为我提供了一个IEnumerable <T>对象,其中T是我的"Village"类,填充了此查询的结果.有些结果是重复的,所以我想在IEnumerable对象上执行Distinct(),如下所示:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)

Distinct()方法不起作用,因为无论是否有相同数量的结果.另一件事,我不知道它是否通常可行,但我无法进入AllianceComparer.Equals()看看可能是什么问题.
我在互联网上找到了这方面的例子,但我似乎无法让我的实现工作.

希望有人在这里看到可能出错的地方!提前致谢!

Meh*_*ari 72

问题出在你身上GetHashCode.您应该更改它以返回哈希码AllianceName.

int IEqualityComparer<Village>.GetHashCode(Village obj)
{
    return obj.AllianceName.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)

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

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


小智 11

return alliances.Select(v => v.AllianceName).Distinct();

这将返回IEnumerable<string>而不是IEnumerable<Village>.


Jac*_*nev 6

或者换行

return alliances.Distinct(new AllianceComparer());
Run Code Online (Sandbox Code Playgroud)

return alliances.Select(v => v.AllianceName).Distinct();
Run Code Online (Sandbox Code Playgroud)