简体   繁体   English

名单不同 <T> 不努力

[英]Distinct of List <T> not workiong

I have this class with comparer 我有比较器班

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();
    }
}

I Tried using Hashset and Distinct but neither one is working. 我尝试使用Hashset和Distinct,但没有一个起作用。 i did not want to do this in db as the list was too big and too for everrrrrrrr. 我不想在db中执行此操作,因为列表太大,对于everrrrrrrr也是如此。 why is this not working in c#? 为什么这在C#中不起作用? i want to get a unique country, city list. 我想获得一个独特的国家/地区城市列表。

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

Your Equals and GetHashCode methods aren't consistent. 您的EqualsGetHashCode方法不一致。 In Equals , you're trimming the city name - but in GetHashCode you're not. Equals ,您正在修剪城市名称-但是在GetHashCode您不是。 That means two equal values can have different hash codes, violating the normal contract. 这意味着两个相等的值可以具有不同的哈希码,这违反了常规合同。

That's the first thing to fix. 那是要解决的第一件事。 I would suggest trimming the city names in the database itself for sanity, and then removing the Trim operations in your Equality check. 我建议修剪数据库本身中的城市名称以保持理智,然后在“ Equality检查中删除“ Trim操作。 That'll make things a lot simpler. 这会使事情变得简单得多。

The second is work out why it was taking a long time in the database: I'd strongly expect it to perform better in the database than locally, especially if you have indexes on the two fields. 第二个是弄清楚为什么它在数据库中要花很长时间的原因 :我强烈希望它在数据库中的性能要好于本地,尤其是当您在两个字段上都有索引时。

The next is to consider making your type immutable if at all possible. 下一步是考虑使类型尽可能不变。 It's generally a bad idea to allow mutable properties of an object to affect equality; 允许对象的可变属性影响相等性通常是一个坏主意。 if you change an equality-sensitive property of an object after using it as a key in a dictionary (or after adding it to a HashSet ) you may well find that you can't retrieve it again, even using the exact same reference. 如果在将对象用作字典中的键之后(或将其添加到HashSet )更改对象的相等性敏感属性,则可能会发现您无法再次检索它,即使使用完全相同的引用也是如此。

EDIT: Also, as Scott noted, you either need to pass in an IEqualityComparer to perform the equality comparison or make your type override the normal Equals and GetHashCode methods. 编辑:另外,正如Scott指出的那样,您要么需要传递IEqualityComparer来执行相等比较, 要么使您的类型重写常规的EqualsGetHashCode方法。 At the moment you're half way between the two (implementing IEqualityComparer<T> , but not actually providing a comparer as an argument to Distinct or the HashSet constructor). 目前,您处于两者之间的一半(实现IEqualityComparer<T> ,但实际上没有提供比较器作为DistinctHashSet构造函数的参数)。 In general it's unusual for a type to implement IEqualityComparer for itself. 通常,对于类型自己实现IEqualityComparer的类型是很不常见的。 Basically you either implement a "natural" equality check in the type or you implement a standalone equality check in a type implementing IEqualityComparer<T> . 基本上,您可以在类型中实现“自然”相等性检查, 或者在实现IEqualityComparer<T>的类型中实现独立的相等性检查。 You don't have to implement IEquatable<T> - just overriding the normal Equals(object) method will work - but it's generally a good idea to implement IEquatable<T> at the same time. 没有实现IEquatable<T> -只是压倒一切正常Equals(object)方法将工作-但它通常是实现一个不错的主意IEquatable<T>在同一时间。

As an aside, I would also suggest computing a hash code without using string concatenation. 顺便说一句,我也建议不使用字符串连接来计算哈希码。 For example: 例如:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + CountryId.GetHashCode();
    hash = hash * 31 + City.GetHashCode();
    return hash;
}

You needed to implment the interface IEquatable<T> not IEqualityComparer<T> (Be sure to read the documentation, especially the " Notes to Implementers " section!). 您需要实现IEquatable<T>接口IEquatable<T>不是IEqualityComparer<T> (请务必阅读文档,尤其是“ 对实现者的注意事项 ”部分!)。 IEqualityComparer is when you want to use a custom comparer other than the default one built in to the class. IEqualityComparer是您要使用自定义比较器而不是内置于该类的默认比较器时。

Also you need to make the changes that Jon mentioned about GetHashCode not matching Equals 你也需要做出改变乔恩提及有关GetHashCode不匹配Equals

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

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