为什么我不能在IEqualityComparer <customer> Equals方法中使用customer.Name.contains(&#34; smith&#34;)

时间:2016-12-09 10:11:34

标签: c# iequalitycomparer

我想使用HashSet.Contains方法,因为它超级快。

 let dateFormatter = DateFormatter()
 dateFormatter.dateFormat = "MMM, dd, yyyy"
 let raceDate = raceDateTextField.text
 let date = dateFormatter.date(from: raceDate!)
 let minimumDate = NSDate()

 if minimumDate.compare(date!) == ComparisonResult.orderedDescending {
 }

我在客户对象上搜索多个属性。

我必须实现IEqualityComparer接口,如:

var hashset = new HashSet<Customer>(customers, new CustomerComparer());
var found = hashset.Contains(new Customer{ Id = "1234", Name = "mit" }); // "mit" instead of an equals "smith" in the comparer.

为什么在我不在.Contains之类的CustomerComparer Equals方法中使用Equals方法时,Equals方法永远不会出现?

2 个答案:

答案 0 :(得分:4)

您实现相等比较器的方式无法正常工作。原因是哈希集和相等比较器如何在内部工作。当DictionaryHashSet对项目进行比较时,它会首先在两个项目上调用GetHashCode。只有当这些哈希码匹配时,它才会确认与后续调用Equals的完全匹配,以避免在哈希码冲突的情况下出现错误匹配。如果您使用示例(x.Name = "smith"y.Name = "mit"),GetHashCode方法将为每个项返回不同的哈希码,并且永远不会调用Equals

这种情况下的解决方案是仅使用Id创建哈希码。这会降低性能,因为你需要更频繁地调用Equals来解决冲突,但这是你必须付出的代价:

public int GetHashCode(Customer obj)
{
    return obj.Id.GetHashCode() ;
}

您还应该考虑的是,您无法保证现有项目是x还是y。因此,您必须在两个方向都使用Contains

public bool Equals(Customer x, Customer y)
{
    return x.Id == y.Id && (x.Name.Contains(y.Name) || y.Name.Contains(x.Name));
}      

答案 1 :(得分:0)

  

为什么在我不在.Contains之类的CustomerComparer Equals方法中使用Equals方法时,Equals方法永远不会出现?

只有当您的&#34;客户&#34;中至少有一个项目出现时,才会触发Equals方法。与您传递给HashSet的Contains方法的Customer对象具有相同哈希码的集合。如果运行以下示例程序,您将看到Equals方法确实被命中:

public static class Program
{
    public class Customer
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

    public class CustomerComparer : IEqualityComparer<Customer>
    {
        public bool Equals(Customer x, Customer y)
        {
            Console.WriteLine("hit!");
            return x.Id == y.Id && x.Name.Contains(y.Name);
        }

        public int GetHashCode(Customer obj)
        {
            return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
        }
    }

    public static void Main()
    {
        List<Customer> customers = new List<Customer>()
        {
            new Customer() { Id = "1234", Name = "smith" },
            new Customer() { Id = "1234", Name = "mit" }
        };
        var hashset = new HashSet<Customer>(customers, new CustomerComparer());
        var found = hashset.Contains(new Customer { Id = "1234", Name = "mit" }); // "mit" instead of an equals "smith" in the comparer.
        Console.WriteLine(found); // = true
    }
}

但如果您从&#34;客户&#34;中删除第二项列出自&#34;史密斯&#34;的哈希码以来不会被击中的等于方法。列表中的客户具有与&#34; smith&#34;不同的哈希码。传递给Contains方法的客户:

List<Customer> customers = new List<Customer>()
        {
            new Customer() { Id = "1234", Name = "smith" }
        };