0

我有这个带比较器的课程

public partial class CityCountryID :IEqualityComparer<CityCountryID>
{

    public string City { get; set; }
    public string CountryId { get; set; }

    public bool Equals(CityCountryID left, CityCountryID right)
    {
        if ((object)left == null && (object)right == null)
        {
            return true;
        }
        if ((object)left == null || (object)right == null)
        {
            return false;
        }
        return left.City.Trim().TrimEnd('\r', '\n') == right.City.Trim().TrimEnd('\r', '\n') 
            && left.CountryId == right.CountryId;
    }

    public int GetHashCode(CityCountryID obj)
    {
        return (obj.City + obj.CountryId).GetHashCode();
    }
}

我尝试使用 Hashset 和 Distinct,但都没有工作。我不想在 db 中这样做,因为列表太大而且对于everrrrrrr 来说也太大了。为什么这在 c# 中不起作用?我想获得一个独特的国家、城市列表。

            List<CityCountryID> CityList = LoadData("GetCityList").ToList();
            //var unique = new HashSet<CityCountryID>(CityList);
            Console.WriteLine("Loading Completed/ Checking Duplicates");
            List<CityCountryID> unique = CityList.Distinct().ToList();
4

2 回答 2

5

你的EqualsGetHashCode方法不一致。在Equals中,您正在修剪城市名称 - 但在 中,GetHashCode您没有。这意味着两个相等的值可以有不同的哈希码,这违反了正常的合同。

这是首先要解决的问题。我建议修剪数据库本身中的城市名称以保持理智,然后删除检查Trim中的操作Equality。这会让事情变得简单很多。

第二个是找出它在数据库中花费很长时间的原因:我强烈希望它在数据库中的性能比在本地更好,特别是如果您在两个字段上都有索引。

接下来是考虑尽可能使您的类型不可变。允许对象的可变属性影响相等性通常是一个坏主意。如果在将对象用作字典中的键(或将其添加到 a 之后HashSet)更改对象的等式敏感属性,您可能会发现即使使用完全相同的引用也无法再次检索它。

编辑:另外,正如 Scott 所指出的,您要么需要传入 anIEqualityComparer来执行相等比较,要么让您的类型覆盖正常的EqualsGetHashCode方法。目前,您介于两者之间(实现IEqualityComparer<T>,但实际上并未提供比较器作为参数DistinctHashSet构造函数)。一般来说,一个类型IEqualityComparer为自己实现是不寻常的。基本上,您要么在类型中实现“自然”相等检查,要么在实现类型中实现独立相等检查IEqualityComparer<T>。您不必实施-只需IEquatable<T>覆盖正常Equals(object)方法将起作用 - 但同时实施通常是一个好主意IEquatable<T>

顺便说一句,我还建议在不使用字符串连接的情况下计算哈希码。例如:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + CountryId.GetHashCode();
    hash = hash * 31 + City.GetHashCode();
    return hash;
}
于 2013-09-08T16:28:54.807 回答
3

IEquatable<T>您不需要实现接口IEqualityComparer<T>(请务必阅读文档,尤其是“对实施者的说明”部分!)。IEqualityComparer 是当您想要使用自定义比较器而不是内置到类中的默认比较器时。

您还需要做出Jon 提到的关于GetHashCode不匹配的更改Equals

于 2013-09-08T16:29:18.247 回答