ConcurrentBag与众不同

时间:2014-10-06 14:56:55

标签: c# linq

我有一个concurrentbag集合,我也添加了项目..现在我最终可能会有多个项目相同(由3个字符串属性定义相同)

我不确定两件事。

  1. 如何从3个属性中生成哈希码
  2. 如果将concurrengbag转换为列表,那么使用自定义派生比较器对其进行区分是正确的方法..
  3. 基本上,目标是让cityProcessor属性NotFoundCities可能包含重复项,然后在addcities方法中只获取非重复列表

      public class CityProcesor
    {
        public ConcurrentBag<CityNotFound> NotFoundCities { get; set; }
        public void AddCities()
        {
            var nonDups = NotFoundCities.ToList().Distinct(new NotFoundCityComparer());
        }
    }
    public class CityNotFound
    {
        public string Name { get; set; }
        public string RegionName { get; set; }
        public string CountryCode { get; set; }
    }
    public class NotFoundCityComparer : IEqualityComparer<CityNotFound>
    {
        public bool Equals(CityNotFound city1, CityNotFound city2)
        {
            return city1.Name == city2.Name && city1.RegionName == city2.RegionName && city1.CountryCode == city2.CountryCode;
        }
        public int GetHashCode(CityNotFound obj)
        {
    
            return 1; //TODO: fix
        }
    }
    

2 个答案:

答案 0 :(得分:1)

您可以使用Jon Skeet DistinctBy中的MoreLinq扩展方法,而不是实现EqualsGetHashCode,该方法既可以作为源代码使用,也可以作为{{3}使用}。

有了DistinctBy,你可以写:

var noDups=myCities.DistinctBy(city=>
                              new {city.Name,city.RegionName,city.CountryCode});

要在比较器中实现GetHashCode,您可以使用任何将返回适度宽范围值的算法 - 它不必是唯一的。

使用ReSharper的模板创建了以下代码段,并对每个属性的哈希码进行异或,例如:

public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = (Name != null ? Name.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (RegionName != null ? RegionName.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (CountryCode != null ? CountryCode.GetHashCode() : 0);
            return hashCode;
        }
    }

答案 1 :(得分:0)

我使用以下方法生成哈希值。我无法记住我在哪里找到了基于它的算法(可能在StackOverflow上的某个地方),但我将它放入以下实用程序类和方法中,以便能够从多个字段/属性创建哈希值:

public static class HashGenerator
{
    private const int seed = 29;
    private const int factor = 31;

    /// <summary>
    /// Method to generate a hash code from multiple objects.
    /// This can be used when overriding GetHashCode by passing in an object's key fields
    /// </summary>
    public static int GetHashCodeFromMany(params object[] objects)
    {
        unchecked
        {
            int hashCode = seed;
            int length = objects.Length;
            for (int counter = 0; counter < length; counter++)
            {
                object obj = objects[counter];
                if (obj != null)
                {
                    int objHashCode = obj.GetHashCode();
                    hashCode *= factor + objHashCode;
                }
            }
            return hashCode;
        }
    }
}

然后可以这样使用:

public override int GetHashCode()
{
    return HashGenerator.GetHashCodeFromMany(Name, RegionName, CountryCode);
}

最好将它与不可变对象一起使用,否则更改关键字段/属性可能会对使用哈希的集合类造成严重破坏。